github.com/System-Glitch/goyave/v2@v2.10.3-0.20200819142921-51011e75d504/docs_src/src/guide/advanced/localization.md (about) 1 --- 2 meta: 3 - name: "og:title" 4 content: "Localization - Goyave" 5 - name: "twitter:title" 6 content: "Localization - Goyave" 7 - name: "title" 8 content: "Localization - Goyave" 9 --- 10 11 # Localization 12 13 [[toc]] 14 15 ## Introduction 16 17 The Goyave framework provides a convenient way to support multiple languages within your application. Out of the box, Goyave only provides the `en-US` language. 18 19 ## Writing language files 20 21 Language files are stored in the `resources/lang` directory. 22 23 :::vue 24 . 25 └── resources 26 └── lang 27 └── en-US (*language name*) 28 ├── fields.json (*optional*) 29 ├── locale.json (*optional*) 30 └── rules.json (*optional*) 31 ::: 32 33 Each language has its own directory and should be named with an [ISO 639-1](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) language code. You can also append a variant to your languages: `en-US`, `en-UK`, `fr-FR`, `fr-CA`, ... **Case is important.** 34 35 Each language directory contains three files. Each file is **optional**. 36 - `fields.json`: field names translations and field-specific rule messages. 37 - `locale.json`: all other language lines. 38 - `rules.json`: validation rules messages. 39 40 ::: tip 41 All directories in the `resources/lang` directory are automatically loaded when the server starts. 42 ::: 43 44 ### Fields 45 46 The `fields.json` file contains the field names translations and their rule-specific messages. Translating field names helps making more expressive messages instead of showing the technical field name to the user. Rule-specific messages let you override a validation rule message for a specific field. 47 48 **Example:** 49 ``` json 50 { 51 "email": { 52 "name": "email address", 53 "rules": { 54 "required": "You must provide an :field." 55 } 56 } 57 } 58 ``` 59 60 This `fields.json` file will change the validation message of the `required` validation rule to `You must provide an email address`. 61 62 ::: tip 63 Learn more about validation messages placeholders in the [validation](../basics/validation.html) section. 64 ::: 65 66 ### Locale 67 68 The `locale.json` file contains all language lines that are not related to validation. This is the place where you should write the language lines for your user interface or for the messages returned by your controllers. 69 70 **Example:** 71 ``` json 72 { 73 "product.created": "The product have been created with success.", 74 "product.deleted": "The product have been deleted with success." 75 } 76 ``` 77 ::: tip 78 It is a good practice to use **dot-separated** names for language lines to help making them clearer and more expressive. 79 ::: 80 81 ### Rules 82 83 The `rules.json` file contains the validation rules messages. These messages can have **[placeholders](../basics/validation.html#placeholders)**, which will be automatically replaced by the validator with dynamic values. If you write custom validation rules, their messages shall be written in this file. 84 85 **Example:** 86 87 ``` json 88 { 89 "integer": "The :field must be an integer.", 90 "starts_with": "The :field must start with one of the following values: :values.", 91 "same": "The :field and the :other must match." 92 } 93 ``` 94 95 #### Type-dependent rules 96 97 The following rules have **type-dependent** messages. That means that their message is different depending on the type of the validated data. 98 99 - `min` 100 - `max` 101 - `size` 102 - `greater_than` 103 - `greater_than_equal` 104 - `lower_than` 105 - `lower_than_equal` 106 107 Type-dependent rules must have a language line for the four following types: 108 - `string` 109 - `numeric` 110 - `array` 111 - `file` 112 113 **Example:** 114 ```json 115 { 116 "min.string": "The :field must be at least :min characters.", 117 "min.numeric": "The :field must be at least :min.", 118 "min.array": "The :field must have at least :min items.", 119 "min.file": "The :field must be at least :min KiB." 120 } 121 ``` 122 123 #### Array validation 124 125 Each rule, except the file-related rules and the `confirmed` rule, can be used to validate array values. If a rule is used to validate an array value and doesn't pass, the rule message `validation.rules.<rule_name>.array` (or `validation.rules.<rule_name>.<type>.array` if the rule is type-dependent) is returned. 126 127 **Example:** 128 ```json 129 { 130 "min.string.array": "The :field values must be at least :min characters.", 131 "min.numeric.array": "The :field values must be at least :min.", 132 "min.array.array": "The :field values must have at least :min items.", 133 "digits.array": "The :field values must be digits only." 134 } 135 ``` 136 137 ### Overrides 138 139 If you define the `en-US` language in your application, the default language lines will be overridden by the ones in your language files, and all the undefined ones will be kept. 140 141 It is possible to load a language directory manually from another location than the stardard `resources/lang` using the `lang.Load()` function. If the loaded language is already available in your application, the newly loaded one will override the previous in the same manner. 142 143 ## Using localization 144 145 When an incoming request enters your application, the core language middleware checks if the `Accept-Language` header is set, and set the `goyave.Request`'s `Lang` attribute accordingly. Localization is handled automatically by the validator. 146 147 To use the localization feature, import the `lang` package: 148 ``` go 149 import "github.com/System-Glitch/goyave/v2/lang" 150 ``` 151 152 The main function of the localization feature is `lang.Get(language, line string)`. This function lets you retrieve a language entry. 153 154 For validation rules and attributes messages, use the following dot-separated paths: 155 - `validation.rules.<rule_name>` 156 - `validation.rules.<rule_name>.string` 157 - `validation.rules.<rule_name>.numeric` 158 - `validation.rules.<rule_name>.array` 159 - `validation.rules.<rule_name>.file` 160 - `validation.fields.<field_name>` 161 - `validation.fields.<field_name>.<rule_name>` 162 163 For normal lines, just use the name of the line. Note that if you have a line called "validation", it won't conflict with the dot-separated paths. If the line cannot be found, or the requested language is not available, the function will return the exact `line` attribute. 164 165 **Example:** 166 ``` go 167 func ControllerHandler(response *goyave.Response, request *goyave.Request) { 168 response.String(http.StatusOK, lang.Get(request.Lang, "my-custom-message")) 169 } 170 ``` 171 172 ### Placeholders 173 174 Language lines can contain **placeholders**. Placeholders are identified by a colon directly followed by the placeholder name: 175 176 ```json 177 "greetings": "Greetings, :username!" 178 ``` 179 180 The last parameter of the `lang.Get()` method is a variadic associative slice of placeholders and their replacement. In the following example, the placeholder `:username` will be replaced with the Name field in the user struct. 181 182 ```go 183 lang.Get("en-US", "greetings", ":username", user.Name) // "Greetings, Taylor!" 184 ``` 185 186 You can provide as many as you want: 187 188 ```go 189 lang.Get("en-US", "greetings-with-date", ":username", user.Name, ":day", "Monday") // "Greetings, Taylor! Today is Monday" 190 ``` 191 192 ::: tip 193 When a placeholder is given, **all occurrences** are replaced. 194 195 ```json 196 "popular": ":product are very popular. :product sales exceeded 1000 last week." 197 ``` 198 ```go 199 lang.Get("en-US", "popular", ":product", "Lawnmowers") 200 // "Lawnmowers are very popular. Lawnmowers sales exceeded 1000 last week." 201 ``` 202 ::: 203 204 ### Localization reference 205 206 ::: table 207 [Get](#lang-get) 208 [Load](#lang-load) 209 [IsAvailable](#lang-isavailable) 210 [GetAvailableLanguages](#lang-getavailablelanguages) 211 [DetectLanguage](#lang-detectlanguage) 212 ::: 213 214 #### lang.Get 215 216 Get a language line. 217 218 | Parameters | Return | 219 |--------------------------|----------| 220 | `lang string` | `string` | 221 | `line string` | | 222 | `placeholders ...string` | | 223 224 **Example:** 225 ``` go 226 fmt.Println(lang.Get("en-US", "my-custom-message")) // "my message" 227 fmt.Println(lang.Get("en-US", "validation.rules.greater_than.string")) // "The :field must be longer than the :other." 228 fmt.Println(lang.Get("en-US", "validation.fields.email")) // "email address" 229 fmt.Println(lang.Get("en-US", "greetings", ":username", user.Name)) // "Greetings, Taylor!" 230 ``` 231 232 #### lang.Load 233 234 Load a language directory. 235 236 | Parameters | Return | 237 |-------------------|--------| 238 | `language string` | `void` | 239 | `path string` | | 240 241 **Example:** 242 ``` go 243 lang.Load("zh", "/path/to/chinese-lang") 244 ``` 245 246 #### lang.IsAvailable 247 248 Returns true if the language is available. 249 250 | Parameters | Return | 251 |---------------|--------| 252 | `lang string` | `bool` | 253 254 **Example:** 255 ``` go 256 fmt.Println(lang.IsAvailable("zh")) // true 257 ``` 258 259 #### lang.GetAvailableLanguages 260 261 Returns a slice of all loaded languages. 262 263 This can be used to generate different routes for all languages supported by your applications such as: 264 ``` 265 /en/products 266 /fr/produits 267 ... 268 ``` 269 270 | Parameters | Return | 271 |---------------|--------| 272 | `lang string` | `bool` | 273 274 **Example:** 275 ``` go 276 fmt.Println(lang.GetAvailableLanguages()) // [en-US zh] 277 ``` 278 279 #### lang.DetectLanguage 280 281 DetectLanguage detects the language to use based on the given lang string. 282 The given lang string can use the HTTP "Accept-Language" header format. 283 284 - If `*` is provided, the default language will be used. 285 - If multiple languages are given, the first available language will be used, and if none are available, the default language will be used. 286 - If no variant is given (for example "en"), the first available variant will be used. 287 288 For example, if `en-US` and `en-UK` are available and the request accepts `en`, `en-US` will be used. 289 290 | Parameters | Return | 291 |---------------|----------| 292 | `lang string` | `string` | 293 294 **Example:** 295 ``` go 296 fmt.Println(lang.DetectLanguage("en, fr-FR;q=0.9")) // "en-US" 297 ```