mirror of
https://github.com/cupcakearmy/svelte-i18n.git
synced 2024-09-28 15:14:45 +02:00
refactor: 💡 split getClientLocale into multiple utilities
This commit is contained in:
parent
a574444f60
commit
6b0ba2b902
@ -64,7 +64,7 @@ After populating your [`$dictionary`](/docs/Dictionary.md) with [`addMessages()`
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
// src/i18n.js
|
// src/i18n.js
|
||||||
import { register, init, getClientLocale } from 'svelte-i18n'
|
import { register, init, getLocaleFromNavigator } from 'svelte-i18n'
|
||||||
|
|
||||||
register('en', () => import('./en.json'))
|
register('en', () => import('./en.json'))
|
||||||
register('en-US', () => import('./en-US.json'))
|
register('en-US', () => import('./en-US.json'))
|
||||||
@ -73,9 +73,7 @@ register('pt', () => import('./pt.json'))
|
|||||||
|
|
||||||
init({
|
init({
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
initialLocale: getClientLocale({
|
initialLocale: getLocaleFromNavigator(),
|
||||||
navigator: true, // i.e 'en-US'
|
|
||||||
}),
|
|
||||||
})
|
})
|
||||||
// starts loading 'en-US' and 'en'
|
// starts loading 'en-US' and 'en'
|
||||||
```
|
```
|
||||||
|
117
docs/Methods.md
117
docs/Methods.md
@ -22,7 +22,7 @@ interface InitOptions {
|
|||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init, getClientLocale } from 'svelte-i18n'
|
import { init } from 'svelte-i18n'
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// fallback to en if current locale is not in the dictionary
|
// fallback to en if current locale is not in the dictionary
|
||||||
@ -68,47 +68,100 @@ init({
|
|||||||
<!-- 123.456,79 € -->
|
<!-- 123.456,79 € -->
|
||||||
```
|
```
|
||||||
|
|
||||||
#### getClientLocale
|
#### getLocaleFromHostname
|
||||||
|
|
||||||
> `import { getClientLocale } from 'svelte-i18n'`
|
> `import { getLocaleFromHostname } from 'svelte-i18n'
|
||||||
|
|
||||||
`getClientLocale(options: GetClientLocaleOptions): void`
|
`getLocaleFromHostname(hostnamePattern: RegExp): string`
|
||||||
|
Utility method to help getting a initial locale based on a pattern of the current `hostname`.
|
||||||
Optional utility method to help getting the initial locale of a user. Use it together with the [`init()`](#init) method.
|
|
||||||
|
|
||||||
```ts
|
|
||||||
interface GetClientLocaleOptions {
|
|
||||||
// the fallback locale to use if no message is found in the current one
|
|
||||||
fallback?: string
|
|
||||||
// when 'true', check the 'window.navigator.language' to set the current locale
|
|
||||||
navigator?: boolean
|
|
||||||
// key to look for a locale on 'window.location.search'
|
|
||||||
// 'example.com?locale=en-US'
|
|
||||||
search?: string
|
|
||||||
// key to look for a locale on 'window.location.hash'
|
|
||||||
// 'example.com#locale=en-US'
|
|
||||||
hash?: string
|
|
||||||
// pattern to look in the window.location.pathname.
|
|
||||||
// It returns the first capturing group.
|
|
||||||
pathname?: RegExp
|
|
||||||
// pattern to look in the window.location.hostname.
|
|
||||||
// It returns the first capturing group.
|
|
||||||
hostname?: RegExp
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Example**:
|
**Example**:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init, getClientLocale } from 'svelte-i18n'
|
import { init, getLocaleFromHostname } from 'svelte-i18n'
|
||||||
|
|
||||||
init({
|
init({
|
||||||
// fallback to en if current locale is not in the dictionary
|
// fallback to en if current locale is not in the dictionary
|
||||||
fallbackLocale: 'en',
|
fallbackLocale: 'en',
|
||||||
initialLocale: getClientLocale({
|
initialLocale: getLocaleFromHostname(/^(.*?)\./),
|
||||||
// based on the user's browser
|
})
|
||||||
navigator: true,
|
```
|
||||||
}),
|
|
||||||
|
#### getLocaleFromPathname
|
||||||
|
|
||||||
|
> `import { getLocaleFromPathname } from 'svelte-i18n'
|
||||||
|
|
||||||
|
`getLocaleFromPathname(pathnamePattern: RegExp): string`
|
||||||
|
|
||||||
|
Utility method to help getting a initial locale based on a pattern of the current `pathname`.
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { init, getLocaleFromPathname } from 'svelte-i18n'
|
||||||
|
|
||||||
|
init({
|
||||||
|
// fallback to en if current locale is not in the dictionary
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
initialLocale: getLocaleFromPathname(/^\/(.*?)\//),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### getLocaleFromNavigator
|
||||||
|
|
||||||
|
> `import { getLocaleFromNavigator } from 'svelte-i18n'
|
||||||
|
|
||||||
|
`getLocaleFromNavigator(): string`
|
||||||
|
|
||||||
|
Utility method to help getting a initial locale based on the browser's `navigator` settings.
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { init, getLocaleFromNavigator } from 'svelte-i18n'
|
||||||
|
|
||||||
|
init({
|
||||||
|
// fallback to en if current locale is not in the dictionary
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
initialLocale: getLocaleFromNavigator(),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### getLocaleFromQueryString
|
||||||
|
|
||||||
|
> `import { getLocaleFromQueryString } from 'svelte-i18n'
|
||||||
|
|
||||||
|
`getLocaleFromQueryString(queryKey: string): string`
|
||||||
|
|
||||||
|
Utility method to help getting a initial locale based on a query string value.
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { init, getLocaleFromQueryString } from 'svelte-i18n'
|
||||||
|
|
||||||
|
init({
|
||||||
|
// fallback to en if current locale is not in the dictionary
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
initialLocale: getLocaleFromQueryString('lang'),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### getLocaleFromHash
|
||||||
|
|
||||||
|
> `import { getLocaleFromHash } from 'svelte-i18n'
|
||||||
|
|
||||||
|
`getLocaleFromHash(): string`
|
||||||
|
|
||||||
|
Utility method to help getting a initial locale based on a hash `{key}={value}` string.
|
||||||
|
|
||||||
|
**Example**:
|
||||||
|
|
||||||
|
```js
|
||||||
|
import { init, getLocaleFromHash } from 'svelte-i18n'
|
||||||
|
|
||||||
|
init({
|
||||||
|
// fallback to en if current locale is not in the dictionary
|
||||||
|
fallbackLocale: 'en',
|
||||||
|
initialLocale: getLocaleFromHash('lang'),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ capital($_('message.id'))
|
|||||||
In `v2`, the [`init`](/docs/Methods.md#init) method could automatically set the initial locale based on some heuristcs from the client:
|
In `v2`, the [`init`](/docs/Methods.md#init) method could automatically set the initial locale based on some heuristcs from the client:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init, getClientLocale } from 'svelte-i18n'
|
import { init } from 'svelte-i18n'
|
||||||
|
|
||||||
init({
|
init({
|
||||||
initialLocale: {
|
initialLocale: {
|
||||||
@ -80,13 +80,19 @@ init({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
However, many people didn't need that kind of extra weight in their apps. So in `v3`, to have the same behavior as `v2`, you have to import the [`getClientLocale`](/docs/Methods.md#getclientlocale) method.
|
However, many people didn't need that kind of extra weight in their apps. So in `v3` you have to explicitly import the utility desired:
|
||||||
|
|
||||||
|
- [`getLocaleFromHostname`](/docs/Methods.md#getlocalefromhostname)
|
||||||
|
- [`getLocaleFromPathname`](/docs/Methods.md#getlocalefrompathname)
|
||||||
|
- [`getLocaleFromNavigator`](/docs/Methods.md#getlocalefromnavigator)
|
||||||
|
- [`getLocaleFromQueryString`](/docs/Methods.md#getlocalefromquerystring)
|
||||||
|
- [`getLocaleFromHash`](/docs/Methods.md#getlocalefromhash)
|
||||||
|
|
||||||
```js
|
```js
|
||||||
import { init, getClientLocale } from 'svelte-i18n'
|
import { init, getLocaleFromNavigator } from 'svelte-i18n'
|
||||||
|
|
||||||
init({
|
init({
|
||||||
initialLocale: getClientLocale({ ... })
|
initialLocale: getLocaleFromNavigator(),
|
||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
9555
package-lock.json
generated
Normal file
9555
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "svelte-i18n",
|
"name": "svelte-i18n",
|
||||||
"version": "3.0.0",
|
"version": "3.0.1",
|
||||||
"main": "dist/runtime.cjs.js",
|
"main": "dist/runtime.cjs.js",
|
||||||
"module": "dist/runtime.esm.js",
|
"module": "dist/runtime.esm.js",
|
||||||
"types": "types/runtime/index.d.ts",
|
"types": "types/runtime/index.d.ts",
|
||||||
|
@ -1,59 +0,0 @@
|
|||||||
import { GetClientLocaleOptions } from '../types'
|
|
||||||
|
|
||||||
const getFromQueryString = (queryString: string, key: string) => {
|
|
||||||
const keyVal = queryString.split('&').find(i => i.indexOf(`${key}=`) === 0)
|
|
||||||
|
|
||||||
if (keyVal) {
|
|
||||||
return keyVal.split('=').pop()
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const getFirstMatch = (base: string, pattern: RegExp) => {
|
|
||||||
const match = pattern.exec(base)
|
|
||||||
// istanbul ignore if
|
|
||||||
if (!match) return null
|
|
||||||
// istanbul ignore else
|
|
||||||
return match[1] || null
|
|
||||||
}
|
|
||||||
|
|
||||||
export const getClientLocale = ({
|
|
||||||
navigator,
|
|
||||||
hash,
|
|
||||||
search,
|
|
||||||
pathname,
|
|
||||||
hostname,
|
|
||||||
}: GetClientLocaleOptions) => {
|
|
||||||
let locale
|
|
||||||
|
|
||||||
// istanbul ignore next
|
|
||||||
if (typeof window === 'undefined') return null
|
|
||||||
|
|
||||||
if (hostname) {
|
|
||||||
locale = getFirstMatch(window.location.hostname, hostname)
|
|
||||||
if (locale) return locale
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pathname) {
|
|
||||||
locale = getFirstMatch(window.location.pathname, pathname)
|
|
||||||
if (locale) return locale
|
|
||||||
}
|
|
||||||
|
|
||||||
if (navigator) {
|
|
||||||
// istanbul ignore else
|
|
||||||
locale = window.navigator.language || window.navigator.languages[0]
|
|
||||||
if (locale) return locale
|
|
||||||
}
|
|
||||||
|
|
||||||
if (search) {
|
|
||||||
locale = getFromQueryString(window.location.search.substr(1), search)
|
|
||||||
if (locale) return locale
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hash) {
|
|
||||||
locale = getFromQueryString(window.location.hash.substr(1), hash)
|
|
||||||
if (locale) return locale
|
|
||||||
}
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
46
src/runtime/includes/localeGetters.ts
Normal file
46
src/runtime/includes/localeGetters.ts
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
const getFromQueryString = (queryString: string, key: string) => {
|
||||||
|
const keyVal = queryString.split('&').find(i => i.indexOf(`${key}=`) === 0)
|
||||||
|
|
||||||
|
if (keyVal) {
|
||||||
|
return keyVal.split('=').pop()
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
const getFirstMatch = (base: string, pattern: RegExp) => {
|
||||||
|
const match = pattern.exec(base)
|
||||||
|
// istanbul ignore if
|
||||||
|
if (!match) return null
|
||||||
|
// istanbul ignore else
|
||||||
|
return match[1] || null
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getLocaleFromHostname = (hostname: RegExp) => {
|
||||||
|
// istanbul ignore next
|
||||||
|
if (typeof window === 'undefined') return null
|
||||||
|
return getFirstMatch(window.location.hostname, hostname)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getLocaleFromPathname = (pathname: RegExp) => {
|
||||||
|
// istanbul ignore next
|
||||||
|
if (typeof window === 'undefined') return null
|
||||||
|
return getFirstMatch(window.location.pathname, pathname)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getLocaleFromNavigator = () => {
|
||||||
|
// istanbul ignore next
|
||||||
|
if (typeof window === 'undefined') return null
|
||||||
|
return window.navigator.language || window.navigator.languages[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getLocaleFromQueryString = (search: string) => {
|
||||||
|
// istanbul ignore next
|
||||||
|
if (typeof window === 'undefined') return null
|
||||||
|
return getFromQueryString(window.location.search.substr(1), search)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getLocaleFromHash = (hash: string) => {
|
||||||
|
// istanbul ignore next
|
||||||
|
if (typeof window === 'undefined') return null
|
||||||
|
return getFromQueryString(window.location.hash.substr(1), hash)
|
||||||
|
}
|
@ -13,7 +13,13 @@ export function waitLocale(locale?: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export { init } from './configs'
|
export { init } from './configs'
|
||||||
export { getClientLocale } from './includes/getClientLocale'
|
export {
|
||||||
|
getLocaleFromHostname,
|
||||||
|
getLocaleFromPathname,
|
||||||
|
getLocaleFromNavigator,
|
||||||
|
getLocaleFromQueryString,
|
||||||
|
getLocaleFromHash,
|
||||||
|
} from './includes/localeGetters'
|
||||||
|
|
||||||
export { $locale as locale } from './stores/locale'
|
export { $locale as locale } from './stores/locale'
|
||||||
|
|
||||||
|
@ -47,17 +47,9 @@ export interface MessagesLoader {
|
|||||||
(): Promise<any>
|
(): Promise<any>
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface GetClientLocaleOptions {
|
|
||||||
navigator?: boolean
|
|
||||||
hash?: string
|
|
||||||
search?: string
|
|
||||||
pathname?: RegExp
|
|
||||||
hostname?: RegExp
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ConfigureOptions {
|
export interface ConfigureOptions {
|
||||||
fallbackLocale: string
|
fallbackLocale: string
|
||||||
initialLocale?: string | GetClientLocaleOptions
|
initialLocale?: string
|
||||||
formats?: Partial<Formats>
|
formats?: Partial<Formats>
|
||||||
loadingDelay?: number
|
loadingDelay?: number
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,10 @@
|
|||||||
import { getClientLocale } from '../../../src/runtime/includes/getClientLocale'
|
import {
|
||||||
|
getLocaleFromQueryString,
|
||||||
|
getLocaleFromHash,
|
||||||
|
getLocaleFromNavigator,
|
||||||
|
getLocaleFromPathname,
|
||||||
|
getLocaleFromHostname,
|
||||||
|
} from '../../../src/runtime/includes/localeGetters'
|
||||||
import { flatObj } from '../../../src/runtime/includes/flatObj'
|
import { flatObj } from '../../../src/runtime/includes/flatObj'
|
||||||
|
|
||||||
describe('getting client locale', () => {
|
describe('getting client locale', () => {
|
||||||
@ -14,96 +20,30 @@ describe('getting client locale', () => {
|
|||||||
|
|
||||||
test('gets the locale based on the passed hash parameter', () => {
|
test('gets the locale based on the passed hash parameter', () => {
|
||||||
window.location.hash = '#locale=en-US&lang=pt-BR'
|
window.location.hash = '#locale=en-US&lang=pt-BR'
|
||||||
expect(
|
expect(getLocaleFromHash('lang')).toBe('pt-BR')
|
||||||
getClientLocale({
|
|
||||||
hash: 'lang',
|
|
||||||
})
|
|
||||||
).toBe('pt-BR')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('gets the locale based on the passed search parameter', () => {
|
test('gets the locale based on the passed search parameter', () => {
|
||||||
window.location.search = '?locale=en-US&lang=pt-BR'
|
window.location.search = '?locale=en-US&lang=pt-BR'
|
||||||
expect(
|
expect(getLocaleFromQueryString('lang')).toBe('pt-BR')
|
||||||
getClientLocale({
|
|
||||||
search: 'lang',
|
|
||||||
})
|
|
||||||
).toBe('pt-BR')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('gets the locale based on the navigator language', () => {
|
test('gets the locale based on the navigator language', () => {
|
||||||
expect(
|
expect(getLocaleFromNavigator()).toBe(window.navigator.language)
|
||||||
getClientLocale({
|
|
||||||
navigator: true,
|
|
||||||
})
|
|
||||||
).toBe(window.navigator.language)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('gets the locale based on the pathname', () => {
|
test('gets the locale based on the pathname', () => {
|
||||||
window.location.pathname = '/en-US/foo/'
|
window.location.pathname = '/en-US/foo/'
|
||||||
expect(
|
expect(getLocaleFromPathname(/^\/(.*?)\//)).toBe('en-US')
|
||||||
getClientLocale({
|
|
||||||
pathname: /^\/(.*?)\//,
|
|
||||||
})
|
|
||||||
).toBe('en-US')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('gets the locale base on the hostname', () => {
|
test('gets the locale base on the hostname', () => {
|
||||||
window.location.hostname = 'pt.example.com'
|
window.location.hostname = 'pt.example.com'
|
||||||
expect(
|
expect(getLocaleFromHostname(/^(.*?)\./)).toBe('pt')
|
||||||
getClientLocale({
|
|
||||||
hostname: /^(.*?)\./,
|
|
||||||
})
|
|
||||||
).toBe('pt')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('hostname precedes pathname', () => {
|
|
||||||
window.location.pathname = '/en-US/foo/'
|
|
||||||
window.location.hostname = 'pt.example.com'
|
|
||||||
expect(
|
|
||||||
getClientLocale({
|
|
||||||
hostname: /^(.*?)\./,
|
|
||||||
pathname: /^\/(.*?)\//,
|
|
||||||
})
|
|
||||||
).toBe('pt')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('pathname precedes navigator', () => {
|
|
||||||
window.location.pathname = '/it-IT/foo/'
|
|
||||||
expect(
|
|
||||||
getClientLocale({
|
|
||||||
pathname: /^\/(.*?)\//,
|
|
||||||
navigator: true,
|
|
||||||
})
|
|
||||||
).toBe('it-IT')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('navigator precedes search', () => {
|
|
||||||
window.location.search = '?lang=pt-BR'
|
|
||||||
expect(
|
|
||||||
getClientLocale({
|
|
||||||
navigator: true,
|
|
||||||
search: 'lang',
|
|
||||||
})
|
|
||||||
).toBe('en-US')
|
|
||||||
})
|
|
||||||
|
|
||||||
test('search precedes hash', () => {
|
|
||||||
window.location.hash = '#lang=pt-BR'
|
|
||||||
window.location.search = '?lang=it-IT'
|
|
||||||
expect(
|
|
||||||
getClientLocale({
|
|
||||||
hash: 'lang',
|
|
||||||
search: 'lang',
|
|
||||||
})
|
|
||||||
).toBe('it-IT')
|
|
||||||
})
|
})
|
||||||
|
|
||||||
test('returns null if no locale was found', () => {
|
test('returns null if no locale was found', () => {
|
||||||
expect(
|
expect(getLocaleFromQueryString('lang')).toBe(null)
|
||||||
getClientLocale({
|
|
||||||
search: 'lang',
|
|
||||||
})
|
|
||||||
).toBe(null)
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user