mirror of
https://github.com/casdoor/casdoor.git
synced 2025-07-04 13:20:19 +08:00
feat: refactor backend i18n (#1373)
* fix: handle the dataSourceName when DB changes * reduce duplication of code * feat: refactor translation error message * feat: use json intsead of ini file * remove useless translation * fix translate problems * remove useless addition * fix pr problems * fix pr problems * fix split problem * use gofumpt to fmt code * use crowdin to execute backend translation * fix pr problems * refactor: change translation file structure same as frontend * delete useless output * update go.mod
This commit is contained in:
@ -44,21 +44,21 @@ func init() {
|
||||
|
||||
func CheckUserSignup(application *Application, organization *Organization, username string, password string, displayName string, firstName string, lastName string, email string, phone string, affiliation string, lang string) string {
|
||||
if organization == nil {
|
||||
return i18n.Translate(lang, "OrgErr.DoNotExist")
|
||||
return i18n.Translate(lang, "check:Organization does not exist")
|
||||
}
|
||||
|
||||
if application.IsSignupItemVisible("Username") {
|
||||
if len(username) <= 1 {
|
||||
return i18n.Translate(lang, "UserErr.NameLessThanTwoCharacters")
|
||||
return i18n.Translate(lang, "check:Username must have at least 2 characters")
|
||||
}
|
||||
if unicode.IsDigit(rune(username[0])) {
|
||||
return i18n.Translate(lang, "UserErr.NameStartWithADigitErr")
|
||||
return i18n.Translate(lang, "check:Username cannot start with a digit")
|
||||
}
|
||||
if util.IsEmailValid(username) {
|
||||
return i18n.Translate(lang, "UserErr.NameIsEmailErr")
|
||||
return i18n.Translate(lang, "check:Username cannot be an email address")
|
||||
}
|
||||
if reWhiteSpace.MatchString(username) {
|
||||
return i18n.Translate(lang, "UserErr.NameCantainWhitSpaceErr")
|
||||
return i18n.Translate(lang, "check:Username cannot contain white spaces")
|
||||
}
|
||||
msg := CheckUsername(username, lang)
|
||||
if msg != "" {
|
||||
@ -66,65 +66,65 @@ func CheckUserSignup(application *Application, organization *Organization, usern
|
||||
}
|
||||
|
||||
if HasUserByField(organization.Name, "name", username) {
|
||||
return i18n.Translate(lang, "UserErr.NameExistedErr")
|
||||
return i18n.Translate(lang, "check:Username already exists")
|
||||
}
|
||||
if HasUserByField(organization.Name, "email", email) {
|
||||
return i18n.Translate(lang, "EmailErr.ExistedErr")
|
||||
return i18n.Translate(lang, "check:Email already exists")
|
||||
}
|
||||
if HasUserByField(organization.Name, "phone", phone) {
|
||||
return i18n.Translate(lang, "PhoneErr.ExistedErr")
|
||||
return i18n.Translate(lang, "check:Phone already exists")
|
||||
}
|
||||
}
|
||||
|
||||
if len(password) <= 5 {
|
||||
return i18n.Translate(lang, "UserErr.PasswordLessThanSixCharacters")
|
||||
return i18n.Translate(lang, "check:Password must have at least 6 characters")
|
||||
}
|
||||
|
||||
if application.IsSignupItemVisible("Email") {
|
||||
if email == "" {
|
||||
if application.IsSignupItemRequired("Email") {
|
||||
return i18n.Translate(lang, "EmailErr.EmptyErr")
|
||||
return i18n.Translate(lang, "check:Email cannot be empty")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
if HasUserByField(organization.Name, "email", email) {
|
||||
return i18n.Translate(lang, "EmailErr.ExistedErr")
|
||||
return i18n.Translate(lang, "check:Email already exists")
|
||||
} else if !util.IsEmailValid(email) {
|
||||
return i18n.Translate(lang, "EmailErr.EmailInvalid")
|
||||
return i18n.Translate(lang, "check:Email is invalid")
|
||||
}
|
||||
}
|
||||
|
||||
if application.IsSignupItemVisible("Phone") {
|
||||
if phone == "" {
|
||||
if application.IsSignupItemRequired("Phone") {
|
||||
return i18n.Translate(lang, "PhoneErr.EmptyErr")
|
||||
return i18n.Translate(lang, "check:Phone cannot be empty")
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
if HasUserByField(organization.Name, "phone", phone) {
|
||||
return i18n.Translate(lang, "PhoneErr.ExistedErr")
|
||||
return i18n.Translate(lang, "check:Phone already exists")
|
||||
} else if organization.PhonePrefix == "86" && !util.IsPhoneCnValid(phone) {
|
||||
return i18n.Translate(lang, "PhoneErr.NumberInvalid")
|
||||
return i18n.Translate(lang, "check:Phone number is invalid")
|
||||
}
|
||||
}
|
||||
|
||||
if application.IsSignupItemVisible("Display name") {
|
||||
if application.GetSignupItemRule("Display name") == "First, last" && (firstName != "" || lastName != "") {
|
||||
if firstName == "" {
|
||||
return i18n.Translate(lang, "UserErr.FirstNameBlankErr")
|
||||
return i18n.Translate(lang, "check:FirstName cannot be blank")
|
||||
} else if lastName == "" {
|
||||
return i18n.Translate(lang, "UserErr.LastNameBlankErr")
|
||||
return i18n.Translate(lang, "check:LastName cannot be blank")
|
||||
}
|
||||
} else {
|
||||
if displayName == "" {
|
||||
return i18n.Translate(lang, "UserErr.DisplayNameBlankErr")
|
||||
return i18n.Translate(lang, "check:DisplayName cannot be blank")
|
||||
} else if application.GetSignupItemRule("Display name") == "Real name" {
|
||||
if !isValidRealName(displayName) {
|
||||
return i18n.Translate(lang, "UserErr.DisplayNameInvalid")
|
||||
return i18n.Translate(lang, "check:DisplayName is not valid real name")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -132,7 +132,7 @@ func CheckUserSignup(application *Application, organization *Organization, usern
|
||||
|
||||
if application.IsSignupItemVisible("Affiliation") {
|
||||
if affiliation == "" {
|
||||
return i18n.Translate(lang, "UserErr.AffiliationBlankErr")
|
||||
return i18n.Translate(lang, "check:Affiliation cannot be blank")
|
||||
}
|
||||
}
|
||||
|
||||
@ -147,7 +147,7 @@ func checkSigninErrorTimes(user *User, lang string) string {
|
||||
|
||||
// deny the login if the error times is greater than the limit and the last login time is less than the duration
|
||||
if seconds > 0 {
|
||||
return fmt.Sprintf(i18n.Translate(lang, "AuthErr.WrongPasswordManyTimes"), seconds/60, seconds%60)
|
||||
return fmt.Sprintf(i18n.Translate(lang, "check:You have entered the wrong password too many times, please wait for %d minutes %d seconds and try again"), seconds/60, seconds%60)
|
||||
}
|
||||
|
||||
// reset the error times
|
||||
@ -167,7 +167,7 @@ func CheckPassword(user *User, password string, lang string) string {
|
||||
|
||||
organization := GetOrganizationByUser(user)
|
||||
if organization == nil {
|
||||
return i18n.Translate(lang, "OrgErr.DoNotExist")
|
||||
return i18n.Translate(lang, "check:Organization does not exist")
|
||||
}
|
||||
|
||||
credManager := cred.GetCredManager(organization.PasswordType)
|
||||
@ -184,9 +184,9 @@ func CheckPassword(user *User, password string, lang string) string {
|
||||
return ""
|
||||
}
|
||||
|
||||
return recordSigninErrorInfo(user)
|
||||
return recordSigninErrorInfo(user, lang)
|
||||
} else {
|
||||
return fmt.Sprintf(i18n.Translate(lang, "LoginErr.UnsupportedPasswordType"), organization.PasswordType)
|
||||
return fmt.Sprintf(i18n.Translate(lang, "check:unsupported password type: %s"), organization.PasswordType)
|
||||
}
|
||||
}
|
||||
|
||||
@ -210,7 +210,7 @@ func checkLdapUserPassword(user *User, password string, lang string) (*User, str
|
||||
if len(searchResult.Entries) == 0 {
|
||||
continue
|
||||
} else if len(searchResult.Entries) > 1 {
|
||||
return nil, i18n.Translate(lang, "LdapErr.MultipleAccounts")
|
||||
return nil, i18n.Translate(lang, "check:Multiple accounts with same uid, please check your ldap server")
|
||||
}
|
||||
|
||||
dn := searchResult.Entries[0].DN
|
||||
@ -221,7 +221,7 @@ func checkLdapUserPassword(user *User, password string, lang string) (*User, str
|
||||
}
|
||||
|
||||
if !ldapLoginSuccess {
|
||||
return nil, i18n.Translate(lang, "LdapErr.PasswordWrong")
|
||||
return nil, i18n.Translate(lang, "check:Ldap user name or password incorrect")
|
||||
}
|
||||
return user, ""
|
||||
}
|
||||
@ -229,11 +229,11 @@ func checkLdapUserPassword(user *User, password string, lang string) (*User, str
|
||||
func CheckUserPassword(organization string, username string, password string, lang string) (*User, string) {
|
||||
user := GetUserByFields(organization, username)
|
||||
if user == nil || user.IsDeleted == true {
|
||||
return nil, i18n.Translate(lang, "UserErr.DoNotExistSignUp")
|
||||
return nil, i18n.Translate(lang, "check:The user doesn't exist")
|
||||
}
|
||||
|
||||
if user.IsForbidden {
|
||||
return nil, i18n.Translate(lang, "LoginErr.UserIsForbidden")
|
||||
return nil, i18n.Translate(lang, "check:The user is forbidden to sign in, please contact the administrator")
|
||||
}
|
||||
|
||||
if user.Ldap != "" {
|
||||
@ -254,13 +254,13 @@ func filterField(field string) bool {
|
||||
|
||||
func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, lang string) (bool, error) {
|
||||
if requestUserId == "" {
|
||||
return false, fmt.Errorf(i18n.Translate(lang, "LoginErr.LoginFirst"))
|
||||
return false, fmt.Errorf(i18n.Translate(lang, "check:Please login first"))
|
||||
}
|
||||
|
||||
if userId != "" {
|
||||
targetUser := GetUser(userId)
|
||||
if targetUser == nil {
|
||||
return false, fmt.Errorf(i18n.Translate(lang, "UserErr.DoNotExist"), userId)
|
||||
return false, fmt.Errorf(i18n.Translate(lang, "check:The user: %s doesn't exist"), userId)
|
||||
}
|
||||
|
||||
userOwner = targetUser.Owner
|
||||
@ -272,7 +272,7 @@ func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, l
|
||||
} else {
|
||||
requestUser := GetUser(requestUserId)
|
||||
if requestUser == nil {
|
||||
return false, fmt.Errorf(i18n.Translate(lang, "LoginErr.SessionOutdated"))
|
||||
return false, fmt.Errorf(i18n.Translate(lang, "check:Session outdated, please login again"))
|
||||
}
|
||||
if requestUser.IsGlobalAdmin {
|
||||
hasPermission = true
|
||||
@ -287,7 +287,7 @@ func CheckUserPermission(requestUserId, userId, userOwner string, strict bool, l
|
||||
}
|
||||
}
|
||||
|
||||
return hasPermission, fmt.Errorf(i18n.Translate(lang, "LoginErr.NoPermission"))
|
||||
return hasPermission, fmt.Errorf(i18n.Translate(lang, "check:You don't have the permission to do this"))
|
||||
}
|
||||
|
||||
func CheckAccessPermission(userId string, application *Application) (bool, error) {
|
||||
@ -322,9 +322,9 @@ func CheckAccessPermission(userId string, application *Application) (bool, error
|
||||
|
||||
func CheckUsername(username string, lang string) string {
|
||||
if username == "" {
|
||||
return i18n.Translate(lang, "UserErr.NameEmptyErr")
|
||||
return i18n.Translate(lang, "check:Empty username.")
|
||||
} else if len(username) > 39 {
|
||||
return i18n.Translate(lang, "UserErr.NameTooLang")
|
||||
return i18n.Translate(lang, "check:Username is too long (maximum is 39 characters).")
|
||||
}
|
||||
|
||||
exclude, _ := regexp.Compile("^[\u0021-\u007E]+$")
|
||||
@ -335,7 +335,7 @@ func CheckUsername(username string, lang string) string {
|
||||
// https://stackoverflow.com/questions/58726546/github-username-convention-using-regex
|
||||
re, _ := regexp.Compile("^[a-zA-Z0-9]+((?:-[a-zA-Z0-9]+)|(?:_[a-zA-Z0-9]+))*$")
|
||||
if !re.MatchString(username) {
|
||||
return i18n.Translate(lang, "UserErr.NameFormatErr")
|
||||
return i18n.Translate(lang, "check:The username may only contain alphanumeric characters, underlines or hyphens, cannot have consecutive hyphens or underlines, and cannot begin or end with a hyphen or underline.")
|
||||
}
|
||||
|
||||
return ""
|
||||
|
@ -18,6 +18,8 @@ import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/casdoor/casdoor/i18n"
|
||||
)
|
||||
|
||||
var reRealName *regexp.Regexp
|
||||
@ -43,7 +45,7 @@ func resetUserSigninErrorTimes(user *User) {
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
||||
}
|
||||
|
||||
func recordSigninErrorInfo(user *User) string {
|
||||
func recordSigninErrorInfo(user *User, lang string) string {
|
||||
// increase failed login count
|
||||
user.SigninWrongTimes++
|
||||
|
||||
@ -56,9 +58,9 @@ func recordSigninErrorInfo(user *User) string {
|
||||
UpdateUser(user.GetId(), user, []string{"signin_wrong_times", "last_signin_wrong_time"}, user.IsGlobalAdmin)
|
||||
leftChances := SigninWrongTimesLimit - user.SigninWrongTimes
|
||||
if leftChances > 0 {
|
||||
return fmt.Sprintf("password is incorrect, you have %d remaining chances", leftChances)
|
||||
return fmt.Sprintf(i18n.Translate(lang, "check_util:password is incorrect, you have %d remaining chances"), leftChances)
|
||||
}
|
||||
|
||||
// don't show the chance error message if the user has no chance left
|
||||
return fmt.Sprintf("You have entered the wrong password too many times, please wait for %d minutes and try again", int(LastSignWrongTimeDuration.Minutes()))
|
||||
return fmt.Sprintf(i18n.Translate(lang, "check_util:You have entered the wrong password too many times, please wait for %d minutes and try again"), int(LastSignWrongTimeDuration.Minutes()))
|
||||
}
|
||||
|
@ -204,14 +204,14 @@ func CheckAccountItemModifyRule(accountItem *AccountItem, user *User, lang strin
|
||||
switch accountItem.ModifyRule {
|
||||
case "Admin":
|
||||
if !(user.IsAdmin || user.IsGlobalAdmin) {
|
||||
return false, fmt.Sprintf(i18n.Translate(lang, "OrgErr.OnlyAdmin"), accountItem.Name)
|
||||
return false, fmt.Sprintf(i18n.Translate(lang, "organization:Only admin can modify the %s."), accountItem.Name)
|
||||
}
|
||||
case "Immutable":
|
||||
return false, fmt.Sprintf(i18n.Translate(lang, "OrgErr.Immutable"), accountItem.Name)
|
||||
return false, fmt.Sprintf(i18n.Translate(lang, "organization:The %s is immutable."), accountItem.Name)
|
||||
case "Self":
|
||||
break
|
||||
default:
|
||||
return false, fmt.Sprintf(i18n.Translate(lang, "OrgErr.UnknownModifyRule"), accountItem.ModifyRule)
|
||||
return false, fmt.Sprintf(i18n.Translate(lang, "organization:Unknown modify rule %s."), accountItem.ModifyRule)
|
||||
}
|
||||
return true, ""
|
||||
}
|
||||
|
@ -277,7 +277,7 @@ func GetCaptchaProviderByOwnerName(applicationId, lang string) (*Provider, error
|
||||
}
|
||||
|
||||
if !existed {
|
||||
return nil, fmt.Errorf(i18n.Translate(lang, "ProviderErr.DoNotExist"), applicationId)
|
||||
return nil, fmt.Errorf(i18n.Translate(lang, "provider:the provider: %s does not exist"), applicationId)
|
||||
}
|
||||
|
||||
return &provider, nil
|
||||
@ -289,7 +289,7 @@ func GetCaptchaProviderByApplication(applicationId, isCurrentProvider, lang stri
|
||||
}
|
||||
application := GetApplication(applicationId)
|
||||
if application == nil || len(application.Providers) == 0 {
|
||||
return nil, fmt.Errorf(i18n.Translate(lang, "ApplicationErr.InvalidID"))
|
||||
return nil, fmt.Errorf(i18n.Translate(lang, "provider:Invalid application id"))
|
||||
}
|
||||
for _, provider := range application.Providers {
|
||||
if provider.Provider == nil {
|
||||
|
@ -45,7 +45,7 @@ func ParseSamlResponse(samlResponse string, providerType string) (string, error)
|
||||
func GenerateSamlLoginUrl(id, relayState, lang string) (string, string, error) {
|
||||
provider := GetProvider(id)
|
||||
if provider.Category != "SAML" {
|
||||
return "", "", fmt.Errorf(i18n.Translate(lang, "ProviderErr.CategoryNotSAML"), provider.Name)
|
||||
return "", "", fmt.Errorf(i18n.Translate(lang, "saml_sp:provider %s's category is not SAML"), provider.Name)
|
||||
}
|
||||
sp, err := buildSp(provider, "")
|
||||
if err != nil {
|
||||
|
@ -130,13 +130,13 @@ func UploadFileSafe(provider *Provider, fullFilePath string, fileBuffer *bytes.B
|
||||
func DeleteFile(provider *Provider, objectKey string, lang string) error {
|
||||
// check fullFilePath is there security issue
|
||||
if strings.Contains(objectKey, "..") {
|
||||
return fmt.Errorf(i18n.Translate(lang, "StorageErr.ObjectKeyNotAllowed"), objectKey)
|
||||
return fmt.Errorf(i18n.Translate(lang, "storage:The objectKey: %s is not allowed"), objectKey)
|
||||
}
|
||||
|
||||
endpoint := getProviderEndpoint(provider)
|
||||
storageProvider := storage.GetStorageProvider(provider.Type, provider.ClientId, provider.ClientSecret, provider.RegionId, provider.Bucket, endpoint)
|
||||
if storageProvider == nil {
|
||||
return fmt.Errorf(i18n.Translate(lang, "ProviderErr.ProviderNotSupported"), provider.Type)
|
||||
return fmt.Errorf(i18n.Translate(lang, "storage:The provider type: %s is not supported"), provider.Type)
|
||||
}
|
||||
|
||||
if provider.Domain == "" {
|
||||
|
@ -241,12 +241,12 @@ func GetTokenByTokenAndApplication(token string, application string) *Token {
|
||||
|
||||
func CheckOAuthLogin(clientId string, responseType string, redirectUri string, scope string, state string, lang string) (string, *Application) {
|
||||
if responseType != "code" && responseType != "token" && responseType != "id_token" {
|
||||
return fmt.Sprintf(i18n.Translate(lang, "ApplicationErr.GrantTypeNotSupport"), responseType), nil
|
||||
return fmt.Sprintf(i18n.Translate(lang, "token:Grant_type: %s is not supported in this application"), responseType), nil
|
||||
}
|
||||
|
||||
application := GetApplicationByClientId(clientId)
|
||||
if application == nil {
|
||||
return i18n.Translate(lang, "TokenErr.InvalidClientId"), nil
|
||||
return i18n.Translate(lang, "token:Invalid client_id"), nil
|
||||
}
|
||||
|
||||
validUri := false
|
||||
@ -257,7 +257,7 @@ func CheckOAuthLogin(clientId string, responseType string, redirectUri string, s
|
||||
}
|
||||
}
|
||||
if !validUri {
|
||||
return fmt.Sprintf(i18n.Translate(lang, "TokenErr.RedirectURIDoNotExist"), redirectUri), application
|
||||
return fmt.Sprintf(i18n.Translate(lang, "token:Redirect URI: %s doesn't exist in the allowed Redirect URI list"), redirectUri), application
|
||||
}
|
||||
|
||||
// Mask application for /api/get-app-login
|
||||
@ -269,7 +269,7 @@ func GetOAuthCode(userId string, clientId string, responseType string, redirectU
|
||||
user := GetUser(userId)
|
||||
if user == nil {
|
||||
return &Code{
|
||||
Message: fmt.Sprintf("The user: %s doesn't exist", userId),
|
||||
Message: fmt.Sprintf("token:The user: %s doesn't exist", userId),
|
||||
Code: "",
|
||||
}
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ func CheckVerificationCode(dest, code, lang string) string {
|
||||
record := getVerificationRecord(dest)
|
||||
|
||||
if record == nil {
|
||||
return i18n.Translate(lang, "PhoneErr.CodeNotSent")
|
||||
return i18n.Translate(lang, "verification:Code has not been sent yet!")
|
||||
}
|
||||
|
||||
timeout, err := conf.GetConfigInt64("verificationCodeTimeout")
|
||||
@ -163,7 +163,7 @@ func CheckVerificationCode(dest, code, lang string) string {
|
||||
|
||||
now := time.Now().Unix()
|
||||
if now-record.Time > timeout*60 {
|
||||
return fmt.Sprintf(i18n.Translate(lang, "PhoneErr.CodeTimeOut"), timeout)
|
||||
return fmt.Sprintf(i18n.Translate(lang, "verification:You should verify your code in %d min!"), timeout)
|
||||
}
|
||||
|
||||
if record.Code != code {
|
||||
|
Reference in New Issue
Block a user