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' // set the key name to look for a locale on 'window.location.hash'
// 'example.com#locale=en-US' // 'example.com#locale=en-US'
hash: 'locale', 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', ask: 'Por favor, digite seu nome',
message: 'Olá {name}, como vai?', 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}}', cats: 'Tenho {n, number} {n,plural,=0{gatos}one{gato}other{gatos}}',
}, },
en: { en: {
@ -92,7 +97,8 @@ dictionary.set({
ask: 'Please type your name', ask: 'Please type your name',
message: 'Hello {name}, how are you?', 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}}', 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('-')) 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 // todo add a urlPattern method/regexp
export const getClientLocale = ({ export const getClientLocale = ({
navigator, navigator,
hash, hash,
search, search,
pathname,
hostname,
default: defaultLocale, default: defaultLocale,
}: { }: {
navigator?: boolean navigator?: boolean
hash?: string hash?: string | RegExp
search?: string search?: string | RegExp
fallback?: string fallback?: string
default?: string default?: string
pathname?: RegExp
hostname?: RegExp
}) => { }) => {
let locale let locale
const getFromURL = (urlPart: string, key: string) => { if (typeof window === 'undefined') {
const keyVal = urlPart return defaultLocale
.substr(1)
.split('&')
.find(i => i.indexOf(key) === 0)
if (keyVal) {
return keyVal.split('=').pop()
}
} }
// istanbul ignore else if (hostname) {
if (typeof window !== 'undefined') { locale = getMatch(window.location.hostname, hostname)
if (navigator) { if (locale) return locale
// 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)
}
} }
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(() => { beforeEach(() => {
delete window.location delete window.location
window.location = { window.location = {
pathname: '/',
hostname: 'example.com',
hash: '', hash: '',
search: '', search: '',
} as any } as any
@ -120,13 +122,11 @@ describe('utilities', () => {
it('should get the locale based on the passed hash parameter', () => { it('should get 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(getClientLocale({ hash: 'locale' })).toBe('en-US')
expect(getClientLocale({ hash: 'lang' })).toBe('pt-BR') expect(getClientLocale({ hash: 'lang' })).toBe('pt-BR')
}) })
it('should get the locale based on the passed search parameter', () => { it('should get 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(getClientLocale({ search: 'locale' })).toBe('en-US')
expect(getClientLocale({ search: 'lang' })).toBe('pt-BR') 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', () => { it('should get the fallback locale', () => {
expect(getClientLocale({ navigator: false, default: 'pt' })).toBe('pt') window.location.pathname = '/en-US/foo/'
expect(getClientLocale({ hash: 'locale', default: 'pt' })).toBe('pt') expect(getClientLocale({ pathname: /^\/(.*?)\// })).toBe('en-US')
})
it('should get the fallback locale', () => {
window.location.hostname = 'pt.example.com'
expect(getClientLocale({ hostname: /^.*?\./ })).toBe('pt')
}) })
}) })