mirror of
https://github.com/cupcakearmy/svelte-i18n.git
synced 2024-09-28 15:14:45 +02:00
docs: ✏️ link to wiki
This commit is contained in:
parent
6fe6c8cca8
commit
02720aa6b6
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,3 +2,4 @@ node_modules
|
|||||||
*.log
|
*.log
|
||||||
dist/
|
dist/
|
||||||
coverage/
|
coverage/
|
||||||
|
docs/
|
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,3 +0,0 @@
|
|||||||
[submodule "docs"]
|
|
||||||
path = docs
|
|
||||||
url = git@github.com:kaisermann/svelte-i18n.wiki.git
|
|
330
README.md
330
README.md
@ -1,333 +1,9 @@
|
|||||||
|
> **WIP document**
|
||||||
|
|
||||||
# svelte-i18n
|
# svelte-i18n
|
||||||
|
|
||||||
> Internationalization for Svelte.
|
> Internationalization for Svelte.
|
||||||
|
|
||||||
<!-- [See Demo](https://svelte-i18n.netlify.com/) -->
|
|
||||||
|
|
||||||
<!-- @import "[TOC]" {cmd="toc" depthFrom=2 depthTo=3 orderedList=false} -->
|
|
||||||
|
|
||||||
<!-- code_chunk_output -->
|
|
||||||
|
|
||||||
- [TODO - WIP](#todo-wip)
|
|
||||||
- [Usage](#usage)
|
|
||||||
- [Locale](#locale)
|
|
||||||
- [The dictionary](#the-dictionary)
|
|
||||||
- [Formatting](#formatting)
|
|
||||||
- [Formatting methods](#formatting-methods)
|
|
||||||
- [Formats](#formats)
|
|
||||||
- [CLI](#cli)
|
|
||||||
- [Options](#options)
|
|
||||||
|
|
||||||
<!-- /code_chunk_output -->
|
|
||||||
|
|
||||||
## TODO - WIP
|
|
||||||
|
|
||||||
- [x] Maybe locale can be a promise so we can await for it on the template;
|
|
||||||
- [ ] Wiki on github;
|
|
||||||
- [x] Find a more flexible way to preload dictionaries so it's possible to preload partial dictionaries.
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
|
|
||||||
`svelte-i18n` uses `stores` to keep track of the current locale, dictionary of messages and the main format function. This way, we keep everything neat, in sync and easy to use on your svelte files.
|
`svelte-i18n` uses `stores` to keep track of the current locale, dictionary of messages and the main format function. This way, we keep everything neat, in sync and easy to use on your svelte files.
|
||||||
|
|
||||||
---
|
### [Go to documentation](https://github.com/kaisermann/svelte-i18n/wiki)
|
||||||
|
|
||||||
### Locale
|
|
||||||
|
|
||||||
The `locale` store defines what is the current locale.
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { locale, dictionary, getClientLocale } from 'svelte-i18n'
|
|
||||||
|
|
||||||
// Set the current locale to en-US
|
|
||||||
locale.set('en-US')
|
|
||||||
|
|
||||||
// This is a store, so we can subscribe to its changes
|
|
||||||
locale.subscribe(() => console.log('locale change'))
|
|
||||||
|
|
||||||
// svelte-i18n exports a method to help getting the current client locale
|
|
||||||
locale.set(
|
|
||||||
getClientLocale({
|
|
||||||
// the fallback locale, if didn't find any
|
|
||||||
fallback: 'en-US',
|
|
||||||
// set to 'true' to check the 'window.navigator.language'
|
|
||||||
navigator: true,
|
|
||||||
// set the key name to look for a locale on 'window.location.search'
|
|
||||||
// 'example.com?locale=en-US'
|
|
||||||
search: 'lang',
|
|
||||||
// set the key name to look for a locale on 'window.location.hash'
|
|
||||||
// 'example.com#locale=en-US'
|
|
||||||
hash: 'locale',
|
|
||||||
// define a pattern to look in the window.location.pathname. It returns the first capturing group.
|
|
||||||
pathname: /^\/(.*?)\//,
|
|
||||||
// define a pattern to look in the window.location.hostname. It returns the first capturing group.
|
|
||||||
hostname: /^\/(.*?)\//,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
```
|
|
||||||
|
|
||||||
If a locale with the format `xx-YY` is not found, `svelte-i18n` looks for the locale `xx` as well.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### The dictionary
|
|
||||||
|
|
||||||
The `dictionary` store defines the dictionary of messages of all locales.
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { locale, dictionary } from 'svelte-i18n'
|
|
||||||
|
|
||||||
// Define a locale dictionary
|
|
||||||
dictionary.set({
|
|
||||||
pt: {
|
|
||||||
message: 'Mensagem',
|
|
||||||
'switch.lang': 'Trocar idioma',
|
|
||||||
greeting: {
|
|
||||||
ask: 'Por favor, digite seu nome',
|
|
||||||
message: 'Olá {name}, como vai?',
|
|
||||||
},
|
|
||||||
photos:
|
|
||||||
'Você {n, plural, =0 {não tem fotos.} =1 {tem uma foto.} other {tem # fotos.}}',
|
|
||||||
cats: 'Tenho {n, number} {n,plural,=0{gatos}one{gato}other{gatos}}',
|
|
||||||
},
|
|
||||||
en: {
|
|
||||||
message: 'Message',
|
|
||||||
'switch.lang': 'Switch language',
|
|
||||||
greeting: {
|
|
||||||
ask: 'Please type your name',
|
|
||||||
message: 'Hello {name}, how are you?',
|
|
||||||
},
|
|
||||||
photos:
|
|
||||||
'You have {n, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}',
|
|
||||||
cats: 'I have {n, number} {n,plural,one{cat}other{cats}}',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
// It's also possible to merge the current dictionary
|
|
||||||
// with other objets
|
|
||||||
dictionary.update(dict => {
|
|
||||||
dict.fr = {
|
|
||||||
// ...french messages
|
|
||||||
}
|
|
||||||
return dict
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
Each language message dictionary can be as deep as you want. Messages can also be looked up by a string represetation of it's path on the dictionary (i.e `greeting.message`).
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### Formatting
|
|
||||||
|
|
||||||
The `_`/`format` store is the actual formatter method. To use it it's simple as any other svelte store.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script>
|
|
||||||
// locale is en
|
|
||||||
import { _ } from 'svelte-i18n'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<input placeholder="{$_('greeting.ask')}" />
|
|
||||||
```
|
|
||||||
|
|
||||||
`svelte-i18n` uses `formatjs` behind the scenes, which means it supports the [ICU message format](http://userguide.icu-project.org/formatparse/messages) for interpolation, pluralization and much more.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<div>
|
|
||||||
{$_('greeting.message', { values: { name: 'John' }})}
|
|
||||||
<!-- Hello John, how are you? -->
|
|
||||||
|
|
||||||
{$_('photos', { values: { n: 0 }})}
|
|
||||||
<!-- You have no photos. -->
|
|
||||||
|
|
||||||
{$_('photos', { values: { n: 12} })}
|
|
||||||
<!-- You have 12 photos. -->
|
|
||||||
</div>
|
|
||||||
```
|
|
||||||
|
|
||||||
### Formatting methods
|
|
||||||
|
|
||||||
#### `_` / `format`
|
|
||||||
|
|
||||||
Main formatting method that formats a localized message by its `id`.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
function(messageId: string, options?: MessageObject): string
|
|
||||||
function(options: MessageObject): string
|
|
||||||
|
|
||||||
interface MessageObject {
|
|
||||||
id?: string
|
|
||||||
locale?: string
|
|
||||||
format?: string
|
|
||||||
default?: string
|
|
||||||
values?: Record<string, string | number | Date>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
- `id`: represents the path to a specific message;
|
|
||||||
- `locale`: forces a specific locale;
|
|
||||||
- `default`: the default value in case of message not found in the current locale;
|
|
||||||
- `format`: the format to be used. See [#formats](#formats);
|
|
||||||
- `values`: properties that should be interpolated in the message;
|
|
||||||
|
|
||||||
You can pass a `string` as the first parameter for a less verbose way of formatting a message.
|
|
||||||
|
|
||||||
```html
|
|
||||||
<script>
|
|
||||||
import { _ } from 'svelte-i18n'
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div>{$_('greeting.ask')}</div>
|
|
||||||
<!-- Please type your name -->
|
|
||||||
|
|
||||||
<div>{$_({ id: 'greeting.ask' })}</div>
|
|
||||||
<!-- Please type your name -->
|
|
||||||
```
|
|
||||||
|
|
||||||
The formatter method also provides some casing utilities:
|
|
||||||
|
|
||||||
- `_.upper` - transforms a localized message into uppercase;
|
|
||||||
- `_.lower` - transforms a localized message into lowercase;
|
|
||||||
- `_.capital` - capitalize a localized message;
|
|
||||||
- `_.title` - transforms the message into title case;
|
|
||||||
|
|
||||||
```html
|
|
||||||
<div>{$_.upper('greeting.ask')}</div>
|
|
||||||
<!-- PLEASE TYPE YOUR NAME -->
|
|
||||||
|
|
||||||
<div>{$_.lower('greeting.ask')}</div>
|
|
||||||
<!-- please type your name -->
|
|
||||||
|
|
||||||
<div>{$_.capital('greeting.ask')}</div>
|
|
||||||
<!-- Please type your name -->
|
|
||||||
|
|
||||||
<div>{$_.title('greeting.ask')}</div>
|
|
||||||
<!-- Please Type Your Name -->
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `_.time`
|
|
||||||
|
|
||||||
Formats a date object into a time string with the specified format (`short`, `medium`, `long`, `full`). Please refer to the [#formats](#formats) section to see available formats.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
function(time: Date, options: MessageObject): string
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
|
||||||
<div>{$_.time(new Date(2019, 3, 24, 23, 45))}</div>
|
|
||||||
<!-- 11:45 PM -->
|
|
||||||
|
|
||||||
<div>{$_.time(new Date(2019, 3, 24, 23, 45), { format: 'medium' } )}</div>
|
|
||||||
<!-- 11:45:00 PM -->
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `_.date`
|
|
||||||
|
|
||||||
Formats a date object into a string with the specified format (`short`, `medium`, `long`, `full`). Please refer to the [#formats](#formats) section to see available formats.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
function(date: Date, options: MessageObject): string
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
|
||||||
<div>{$_.date(new Date(2019, 3, 24, 23, 45))}</div>
|
|
||||||
<!-- 4/24/19 -->
|
|
||||||
|
|
||||||
<div>{$_.date(new Date(2019, 3, 24, 23, 45), { format: 'medium' } )}</div>
|
|
||||||
<!-- Apr 24, 2019 -->
|
|
||||||
```
|
|
||||||
|
|
||||||
#### `_.number`
|
|
||||||
|
|
||||||
Formats a number with the specified locale and format. Please refer to the [#formats](#formats) section to see available formats.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
function(number: number, options: MessageObject): string
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
|
||||||
<div>{$_.number(100000000)}</div>
|
|
||||||
<!-- 100,000,000 -->
|
|
||||||
|
|
||||||
<div>{$_.number(100000000, { locale: 'pt' })}</div>
|
|
||||||
<!-- 100.000.000 -->
|
|
||||||
```
|
|
||||||
|
|
||||||
### Formats
|
|
||||||
|
|
||||||
`svelte-i18n` comes with a set of default `number`, `time` and `date` formats:
|
|
||||||
|
|
||||||
**Number:**
|
|
||||||
|
|
||||||
- `currency`: `{ style: 'currency' }`
|
|
||||||
- `percent`: `{ style: 'percent' }`
|
|
||||||
- `scientific`: `{ notation: 'scientific' }`
|
|
||||||
- `engineering`: `{ notation: 'engineering' }`
|
|
||||||
- `compactLong`: `{ notation: 'compact', compactDisplay: 'long' }`
|
|
||||||
- `compactShort`: `{ notation: 'compact', compactDisplay: 'short' }`
|
|
||||||
|
|
||||||
**Date:**
|
|
||||||
|
|
||||||
- `short`: `{ month: 'numeric', day: 'numeric', year: '2-digit' }`
|
|
||||||
- `medium`: `{ month: 'short', day: 'numeric', year: 'numeric' }`
|
|
||||||
- `long`: `{ month: 'long', day: 'numeric', year: 'numeric' }`
|
|
||||||
- `full`: `{ weekday: 'long', month: 'long', day: 'numeric', year: 'numeric' }`
|
|
||||||
|
|
||||||
**Time:**
|
|
||||||
|
|
||||||
- `short`: `{ hour: 'numeric', minute: 'numeric' }`
|
|
||||||
- `medium`: `{ hour: 'numeric', minute: 'numeric', second: 'numeric' }`
|
|
||||||
- `long`: `{ hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short' }`
|
|
||||||
- `full`: `{ hour: 'numeric', minute: 'numeric', second: 'numeric', timeZoneName: 'short' }`
|
|
||||||
|
|
||||||
It's possible to define custom format styles via the `addCustomFormats` method if you need to supply a set of options to the underlying `Intl` formatter.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
function addCustomFormats(formatsObject: Formats): void
|
|
||||||
|
|
||||||
interface Formats {
|
|
||||||
number: Record<string, Intl.NumberFormatOptions>
|
|
||||||
date: Record<string, Intl.DateTimeFormatOptions>
|
|
||||||
time: Record<string, Intl.DateTimeFormatOptions>
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
Please refer to the [Intl.NumberFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat) and [Intl.DateTimeFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DateTimeFormat) documentations to see available formatting options.
|
|
||||||
|
|
||||||
**Example**:
|
|
||||||
|
|
||||||
```js
|
|
||||||
import { addCustomFormats } from 'svelte-i18n'
|
|
||||||
|
|
||||||
addCustomFormats({
|
|
||||||
number: {
|
|
||||||
EUR: {
|
|
||||||
style: 'currency',
|
|
||||||
currency: 'EUR',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
```
|
|
||||||
|
|
||||||
```html
|
|
||||||
<div>
|
|
||||||
{$_.number(123456.789, { format: 'EUR' })}
|
|
||||||
</div>
|
|
||||||
<!-- 123.456,79 € -->
|
|
||||||
```
|
|
||||||
|
|
||||||
## CLI
|
|
||||||
|
|
||||||
`svelte-i18n` provides a command-line interface to extract all your messages to the `stdout` or to a specific JSON file.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ svelte-i18n extract [options] <glob-pattern> [output-file]
|
|
||||||
```
|
|
||||||
|
|
||||||
### Options
|
|
||||||
|
|
||||||
- `-s, --shallow` - extract all messages to a shallow object, without creating nested objects. Default: `false`.
|
|
||||||
|
|
||||||
- `--overwrite` - overwrite the content of the `output` file instead of just appending missing properties. Default: `false`.
|
|
||||||
|
|
||||||
- `-c, --configDir` - define the directory of a [`svelte.config.js`](https://github.com/UnwrittenFun/svelte-vscode#generic-setup) in case your svelte components need to be preprocessed.
|
|
||||||
|
1
docs
1
docs
@ -1 +0,0 @@
|
|||||||
Subproject commit acadff6027a315e011a7157ae3b139d5e4cc3ae5
|
|
@ -14,7 +14,6 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"compression": "^1.7.1",
|
"compression": "^1.7.1",
|
||||||
"polka": "next",
|
"polka": "next",
|
||||||
"rollup-plugin-json": "^4.0.0",
|
|
||||||
"sirv": "^0.4.0",
|
"sirv": "^0.4.0",
|
||||||
"svelte-i18n": "^2.0.0-alpha.2"
|
"svelte-i18n": "^2.0.0-alpha.2"
|
||||||
},
|
},
|
||||||
@ -24,6 +23,7 @@
|
|||||||
"@babel/plugin-transform-runtime": "^7.0.0",
|
"@babel/plugin-transform-runtime": "^7.0.0",
|
||||||
"@babel/preset-env": "^7.0.0",
|
"@babel/preset-env": "^7.0.0",
|
||||||
"@babel/runtime": "^7.0.0",
|
"@babel/runtime": "^7.0.0",
|
||||||
|
"@rollup/plugin-json": "^4.0.0",
|
||||||
"@rollup/plugin-replace": "^2.2.0",
|
"@rollup/plugin-replace": "^2.2.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"rollup": "^1.12.0",
|
"rollup": "^1.12.0",
|
||||||
|
@ -3,7 +3,7 @@ import replace from '@rollup/plugin-replace'
|
|||||||
import commonjs from 'rollup-plugin-commonjs'
|
import commonjs from 'rollup-plugin-commonjs'
|
||||||
import svelte from 'rollup-plugin-svelte'
|
import svelte from 'rollup-plugin-svelte'
|
||||||
import babel from 'rollup-plugin-babel'
|
import babel from 'rollup-plugin-babel'
|
||||||
import json from 'rollup-plugin-json'
|
import json from '@rollup/plugin-json'
|
||||||
import { terser } from 'rollup-plugin-terser'
|
import { terser } from 'rollup-plugin-terser'
|
||||||
import config from 'sapper/config/rollup.js'
|
import config from 'sapper/config/rollup.js'
|
||||||
|
|
||||||
|
@ -677,6 +677,13 @@
|
|||||||
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.7.tgz#e0f307ab768b799aa8668343ce0df6601f29b9b1"
|
resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.7.tgz#e0f307ab768b799aa8668343ce0df6601f29b9b1"
|
||||||
integrity sha512-DOQhemlNfLQ7FZ6gdThARbeIjfhdM5fIqoPtgOJkO27r8A4njwiQSqx+qbReuIHEtx3fJyjSn2spMnsAHc0rFQ==
|
integrity sha512-DOQhemlNfLQ7FZ6gdThARbeIjfhdM5fIqoPtgOJkO27r8A4njwiQSqx+qbReuIHEtx3fJyjSn2spMnsAHc0rFQ==
|
||||||
|
|
||||||
|
"@rollup/plugin-json@^4.0.0":
|
||||||
|
version "4.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.0.0.tgz#4462e83c7ad5544bef4a601a6e8450daedc4b69b"
|
||||||
|
integrity sha512-Z65CtEVWv40+ri4CvmswyhtuUtki9yP5p0UJN/GyCKKyU4jRuDS9CG0ZuV7/XuS7zGkoajyE7E4XBEaC4GW62A==
|
||||||
|
dependencies:
|
||||||
|
rollup-pluginutils "^2.5.0"
|
||||||
|
|
||||||
"@rollup/plugin-replace@^2.2.0":
|
"@rollup/plugin-replace@^2.2.0":
|
||||||
version "2.2.1"
|
version "2.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.2.1.tgz#94af20cb3d70cccdcec991d1f97dd373936ec544"
|
resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.2.1.tgz#94af20cb3d70cccdcec991d1f97dd373936ec544"
|
||||||
@ -1447,13 +1454,6 @@ rollup-plugin-commonjs@^10.0.0:
|
|||||||
resolve "^1.11.0"
|
resolve "^1.11.0"
|
||||||
rollup-pluginutils "^2.8.1"
|
rollup-pluginutils "^2.8.1"
|
||||||
|
|
||||||
rollup-plugin-json@^4.0.0:
|
|
||||||
version "4.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz#a18da0a4b30bf5ca1ee76ddb1422afbb84ae2b9e"
|
|
||||||
integrity sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow==
|
|
||||||
dependencies:
|
|
||||||
rollup-pluginutils "^2.5.0"
|
|
||||||
|
|
||||||
rollup-plugin-node-resolve@^5.2.0:
|
rollup-plugin-node-resolve@^5.2.0:
|
||||||
version "5.2.0"
|
version "5.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz#730f93d10ed202473b1fb54a5997a7db8c6d8523"
|
resolved "https://registry.yarnpkg.com/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz#730f93d10ed202473b1fb54a5997a7db8c6d8523"
|
||||||
|
Loading…
Reference in New Issue
Block a user