feat: 🎸 add pathname and hostname pattern matching

This commit is contained in:
Christian Kaisermann 2019-11-20 17:10:40 -03:00
parent bf5ad6e387
commit b19b69050e
3 changed files with 78 additions and 33 deletions

View File

@ -58,7 +58,11 @@ locale.set(
// 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: /^\/(.*?)\//,
})
)
```
@ -82,7 +86,8 @@ dictionary.set({
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.}}',
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: {
@ -92,7 +97,8 @@ dictionary.set({
ask: 'Please type your name',
message: 'Hello {name}, how are you?',
},
photos: 'You have {n, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}',
photos:
'You have {n, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}',
cats: 'I have {n, number} {n,plural,one{cat}other{cats}}',
},
})

View File

@ -23,47 +23,77 @@ export function getLocalesFrom(locale: string) {
return locale.split('-').map((_, i, arr) => arr.slice(0, i + 1).join('-'))
}
const getFromURL = (urlPart: string, key: string) => {
const keyVal = urlPart
.substr(1)
.split('&')
.find(i => i.indexOf(key) === 0)
if (keyVal) {
return keyVal.split('=').pop()
}
}
const getMatch = (base: string, pattern: RegExp) => {
const match = pattern.exec(base)
if (!match) return null
return match[1] || null
}
// todo add a urlPattern method/regexp
export const getClientLocale = ({
navigator,
hash,
search,
pathname,
hostname,
default: defaultLocale,
}: {
navigator?: boolean
hash?: string
search?: string
hash?: string | RegExp
search?: string | RegExp
fallback?: string
default?: string
pathname?: RegExp
hostname?: RegExp
}) => {
let locale
const getFromURL = (urlPart: string, key: string) => {
const keyVal = urlPart
.substr(1)
.split('&')
.find(i => i.indexOf(key) === 0)
if (keyVal) {
return keyVal.split('=').pop()
}
if (typeof window === 'undefined') {
return defaultLocale
}
// istanbul ignore else
if (typeof window !== 'undefined') {
if (navigator) {
// istanbul ignore next
locale = window.navigator.language || window.navigator.languages[0]
}
if (search && !locale) {
locale = getFromURL(window.location.search, search)
}
if (hash && !locale) {
locale = getFromURL(window.location.hash, hash)
}
if (hostname) {
locale = getMatch(window.location.hostname, hostname)
if (locale) return locale
}
return locale || defaultLocale
if (pathname) {
locale = getMatch(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 =
typeof search === 'string'
? getFromURL(window.location.search, search)
: getMatch(window.location.search, search)
if (locale) return locale
}
if (hash) {
locale =
typeof hash === 'string'
? getFromURL(window.location.hash, hash)
: getMatch(window.location.hash, hash)
if (locale) return locale
}
return defaultLocale
}

View File

@ -113,6 +113,8 @@ describe('utilities', () => {
beforeEach(() => {
delete window.location
window.location = {
pathname: '/',
hostname: 'example.com',
hash: '',
search: '',
} as any
@ -120,13 +122,11 @@ describe('utilities', () => {
it('should get the locale based on the passed hash parameter', () => {
window.location.hash = '#locale=en-US&lang=pt-BR'
expect(getClientLocale({ hash: 'locale' })).toBe('en-US')
expect(getClientLocale({ hash: 'lang' })).toBe('pt-BR')
})
it('should get the locale based on the passed search parameter', () => {
window.location.search = '?locale=en-US&lang=pt-BR'
expect(getClientLocale({ search: 'locale' })).toBe('en-US')
expect(getClientLocale({ search: 'lang' })).toBe('pt-BR')
})
@ -136,9 +136,18 @@ describe('utilities', () => {
)
})
it('should get the default locale', () => {
expect(getClientLocale({ default: 'pt' })).toBe('pt')
})
it('should get the fallback locale', () => {
expect(getClientLocale({ navigator: false, default: 'pt' })).toBe('pt')
expect(getClientLocale({ hash: 'locale', default: 'pt' })).toBe('pt')
window.location.pathname = '/en-US/foo/'
expect(getClientLocale({ pathname: /^\/(.*?)\// })).toBe('en-US')
})
it('should get the fallback locale', () => {
window.location.hostname = 'pt.example.com'
expect(getClientLocale({ hostname: /^.*?\./ })).toBe('pt')
})
})