Skip to content

Commit

Permalink
feat: expose API for detecting browser locale (#1022)
Browse files Browse the repository at this point in the history
Add $i18n. getBrowserLocale() for returning locale detected from the browser.

Resolves #1018
  • Loading branch information
ThibaultNocchi authored Jan 11, 2021
1 parent b6a0c61 commit ac75635
Show file tree
Hide file tree
Showing 6 changed files with 37 additions and 10 deletions.
10 changes: 9 additions & 1 deletion docs/content/en/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ Instance of [VueI18n class](http://kazupon.github.io/vue-i18n/api/#vuei18n-class

Switches locale of the app to specified locale code. If `useCookie` option is enabled, locale cookie will be updated with new value. If prefixes are enabled (`strategy` other than `no_prefix`), will navigate to new locale's route.

#### getBrowserLocale

- **Arguments**:
- no arguments
- **Returns**: `string | undefined`

Returns browser locale code filtered against the ones defined in options.

### Properties

#### defaultLocale
Expand All @@ -112,7 +120,7 @@ Instance of [VueI18n class](http://kazupon.github.io/vue-i18n/api/#vuei18n-class
- **Type**: `Array<string | LocaleObject>`

List of locales as defined in options.

#### localeProperties

- **Type**: `LocaleObject`
Expand Down
8 changes: 8 additions & 0 deletions docs/content/es/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,14 @@ Instance of [VueI18n class](http://kazupon.github.io/vue-i18n/api/#vuei18n-class

Switches locale of the app to specified locale code. If `useCookie` option is enabled, locale cookie will be updated with new value. If prefixes are enabled (`strategy` other than `no_prefix`), will navigate to new locale's route.

#### getBrowserLocale

- **Parámetros**:
- sin parámetros
- **Devuelve**: `string | undefined`

Devuelve el código del idioma que utiliza el navegador, filtrado según los códigos definidos en las opciones.

### Properties

#### defaultLocale
Expand Down
20 changes: 15 additions & 5 deletions src/templates/plugin.main.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,17 @@ export default async (context) => {
return [null, null]
}

const getBrowserLocale = () => {
if (process.client && typeof navigator !== 'undefined' && navigator.languages) {
// Get browser language either from navigator if running on client side, or from the headers
return matchBrowserLocale(locales, navigator.languages)
} else if (req && typeof req.headers['accept-language'] !== 'undefined') {
return matchBrowserLocale(locales, parseAcceptLanguage(req.headers['accept-language']))
} else {
return undefined
}
}

const doDetectBrowserLanguage = route => {
// Browser detection is ignored if it is a nuxt generate.
if (process.static && process.server) {
Expand All @@ -222,11 +233,9 @@ export default async (context) => {

if (useCookie && (matchedLocale = app.i18n.getLocaleCookie())) {
// Get preferred language from cookie if present and enabled
} else if (process.client && typeof navigator !== 'undefined' && navigator.languages) {
// Get browser language either from navigator if running on client side, or from the headers
matchedLocale = matchBrowserLocale(locales, navigator.languages)
} else if (req && typeof req.headers['accept-language'] !== 'undefined') {
matchedLocale = matchBrowserLocale(locales, parseAcceptLanguage(req.headers['accept-language']))
} else {
// Try to get locale from either navigator or header detection
matchedLocale = getBrowserLocale()
}

const finalLocale = matchedLocale || fallbackLocale
Expand All @@ -250,6 +259,7 @@ export default async (context) => {
i18n.setLocaleCookie = locale => setLocaleCookie(locale, res, { useCookie, cookieDomain, cookieKey, cookieSecure, cookieCrossOrigin })
i18n.getLocaleCookie = () => getLocaleCookie(req, { useCookie, cookieKey, localeCodes })
i18n.setLocale = (locale) => loadAndSetLocale(locale)
i18n.getBrowserLocale = () => getBrowserLocale()
i18n.__baseUrl = app.i18n.__baseUrl
}

Expand Down
4 changes: 2 additions & 2 deletions src/templates/utils-common.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export const parseAcceptLanguage = input => {
* Find locale code that best matches provided list of browser locales.
* @param {(string[]|Object[])} appLocales The user-configured locale codes that are to be matched.
* @param {string[]} browserLocales The locales to match against configured.
* @return {string?}
* @return {string|undefined}
*/
export const matchBrowserLocale = (appLocales, browserLocales) => {
/** @type {{ code: string, score: number }[]} */
Expand Down Expand Up @@ -63,7 +63,7 @@ export const matchBrowserLocale = (appLocales, browserLocales) => {
})
}

return matchedLocales.length ? matchedLocales[0].code : null
return matchedLocales.length ? matchedLocales[0].code : undefined
}

/**
Expand Down
4 changes: 2 additions & 2 deletions test/unit.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ describe('parsePages', () => {
test('triggers warning with invalid in-component options', async () => {
const { extractComponentOptions } = await import('../src/helpers/components')

const spy = jest.spyOn(console, 'warn').mockImplementation(() => {})
const spy = jest.spyOn(console, 'warn').mockImplementation(() => { })
const options = extractComponentOptions(path.join(__dirname, './fixture/typescript/pages/invalidOptions.vue'))
expect(spy.mock.calls[0][0]).toContain('Error parsing')
spy.mockRestore()
Expand Down Expand Up @@ -64,7 +64,7 @@ describe('matchBrowserLocale', () => {
const appLocales = ['pl', 'fr']
const browserLocales = ['en-US', 'en']

expect(matchBrowserLocale(appLocales, browserLocales)).toBe(null)
expect(matchBrowserLocale(appLocales, browserLocales)).toBe(undefined)
})

test('matches full locale with mixed short and full, full having highest rank', () => {
Expand Down
1 change: 1 addition & 0 deletions types/vue.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ declare module 'vue-i18n' {
getLocaleCookie() : string | undefined
setLocaleCookie(locale: string) : undefined
setLocale(locale: string) : Promise<undefined>
getBrowserLocale() : string | undefined
}
}

Expand Down

0 comments on commit ac75635

Please sign in to comment.