Skip to content

Commit

Permalink
feat!: support lang option for path and query detection APIs (#27)
Browse files Browse the repository at this point in the history
  • Loading branch information
kazupon authored Oct 17, 2023
1 parent 15e6f68 commit 596206c
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 26 deletions.
36 changes: 25 additions & 11 deletions src/http.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,17 @@ describe('getPathLanguage', () => {
expect(getPathLanguage(url)).toBe('en')
})

test('default language, when the language is not detected', () => {
expect(getPathLanguage('/')).toBe('en-US')
})

test('parser option', () => {
const nullLangParser = () => 'null'
expect(getPathLanguage('/en/foo', nullLangParser)).toBe('null')
expect(getPathLanguage('/en/foo', { parser: nullLangParser })).toBe('null')
})

test('lang option', () => {
expect(getPathLanguage('/', { lang: 'ja' })).toBe('ja')
})
})

Expand All @@ -32,11 +40,16 @@ describe('getPathLocale', () => {
expect(getPathLocale(url).toString()).toBe('ja-JP')
})

test('default locale, when the language is not detected', () => {
expect(getPathLocale('/').toString()).toBe('en-US')
})

test('RangeError', () => {
const nullLangParser = () => 'null'
expect(() => getPathLocale('/en/foo', nullLangParser)).toThrowError(
RangeError,
)
expect(() => getPathLocale('/en/foo', { parser: nullLangParser }))
.toThrowError(
RangeError,
)
})
})

Expand All @@ -47,7 +60,7 @@ describe('getQueryLanguage', () => {

test('URL instance', () => {
const url = new URL('https://example.com/?locale=ja-JP')
expect(getQueryLanguage(url, 'locale')).toBe('ja-JP')
expect(getQueryLanguage(url, { name: 'locale' })).toBe('ja-JP')
})

test('URLSearchParams instance', () => {
Expand All @@ -56,15 +69,16 @@ describe('getQueryLanguage', () => {
expect(getQueryLanguage(params)).toBe('ja-JP')
})

test('empty', () => {
test('default language, when the language is not detected', () => {
const params = new URLSearchParams()
expect(getQueryLanguage(params)).toBe('')
expect(getQueryLanguage(params)).toBe('en-US')
})
})

describe('getQueryLocale', () => {
test('basic', () => {
expect(getQueryLocale('lang=en-US&flag=1', 'lang').toString()).toBe('en-US')
expect(getQueryLocale('lang=en-US&flag=1', { name: 'lang' }).toString())
.toBe('en-US')
})

test('URL instance', () => {
Expand All @@ -75,11 +89,11 @@ describe('getQueryLocale', () => {
test('URLSearchParams instance', () => {
const params = new URLSearchParams('lang=ja-JP')
params.set('flag', '1')
expect(getQueryLocale(params, 'lang').toString()).toBe('ja-JP')
expect(getQueryLocale(params, { name: 'lang' }).toString()).toBe('ja-JP')
})

test('RangeError', () => {
test('default language, when the language is not detected', () => {
const params = new URLSearchParams()
expect(() => getQueryLocale(params)).toThrowError(RangeError)
expect(getQueryLanguage(params)).toBe('en-US')
})
})
44 changes: 29 additions & 15 deletions src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
toLocale,
validateLangTag,
} from './shared.ts'
import { ACCEPT_LANGUAGE_HEADER } from './constants.ts'
import { ACCEPT_LANGUAGE_HEADER, DEFAULT_LANG_TAG } from './constants.ts'

import type { PathLanguageParser } from './shared.ts'
// import type { CookieSerializeOptions } from 'cookie-es'
Expand Down Expand Up @@ -175,36 +175,43 @@ export function getExistCookies(
return setCookies as string[]
}

export type PathOptions = {
lang?: string
parser?: PathLanguageParser
}

/**
* get the language from the path
*
* @param {string | URL} path the target path
* @param {PathLanguageParser} parser the path language parser, optional
* @param {PathOptions['lang']} options.lang the language tag, which is as default `'en-US'`. optional
* @param {PathOptions['parser']} options.parser the path language parser, optional
*
* @returns {string} the language that is parsed by the path language parser, if the language is not detected, return an empty string.
* @returns {string} the language that is parsed by the path language parser, if the language is not detected, return a `options.lang` value
*/
export function getPathLanguage(
path: string | URL,
parser?: PathLanguageParser,
{ lang = DEFAULT_LANG_TAG, parser = pathLanguageParser }: PathOptions = {},
): string {
return (parser || pathLanguageParser)(path)
return (parser || pathLanguageParser)(path) || lang
}

/**
* get the locale from the path
*
* @param {string | URL} path the target path
* @param {PathLanguageParser} parser the path language parser, optional
* @param {PathOptions['lang']} options.lang the language tag, which is as default `'en-US'`. optional
* @param {PathOptions['parser']} options.parser the path language parser, optional
*
* @throws {RangeError} Throws the {@link RangeError} if the language in the path, that is not a well-formed BCP 47 language tag.
*
* @returns {Intl.Locale} The locale that resolved from path
*/
export function getPathLocale(
path: string | URL,
parser?: PathLanguageParser,
{ lang = DEFAULT_LANG_TAG, parser = pathLanguageParser }: PathOptions = {},
): Intl.Locale {
return new Intl.Locale(getPathLanguage(path, parser))
return new Intl.Locale(getPathLanguage(path, { lang, parser }))
}

function getURLSearchParams(
Expand All @@ -219,35 +226,42 @@ function getURLSearchParams(
}
}

export type QueryOptions = {
lang?: string
name?: string
}

/**
* get the language from the query
*
* @param {string | URL | URLSearchParams} query the target query
* @param {string} name the query param name, default `'lang'`
* @param {QueryOptions['lang']} options.lang the language tag, which is as default `'en-US'`. optional
* @param {QueryOptions['name']} options.name the query param name, default `'lang'`. optional
*
* @returns {string} the language from query, if the language is not detected, return an empty string.
* @returns {string} the language from query, if the language is not detected, return an `options.lang` option string.
*/
export function getQueryLanguage(
query: string | URL | URLSearchParams,
name = 'lang',
{ lang = DEFAULT_LANG_TAG, name = 'lang' }: QueryOptions = {},
): string {
const queryParams = getURLSearchParams(query)
return queryParams.get(name) || ''
return queryParams.get(name) || lang
}

/**
* get the locale from the query
*
* @param {string | URL | URLSearchParams} query the target query
* @param {string} name the query param name, default `'locale'`
* @param {QueryOptions['lang']} options.lang the language tag, which is as default `'en-US'`. optional
* @param {QueryOptions['name']} options.name the query param name, default `'locale'`. optional
*
* @throws {RangeError} Throws the {@link RangeError} if the language in the query, that is not a well-formed BCP 47 language tag.
*
* @returns {Intl.Locale} The locale that resolved from query
*/
export function getQueryLocale(
query: string | URL | URLSearchParams,
name = 'locale',
{ lang = DEFAULT_LANG_TAG, name = 'locale' }: QueryOptions = {},
): Intl.Locale {
return new Intl.Locale(getQueryLanguage(query, name))
return new Intl.Locale(getQueryLanguage(query, { lang, name }))
}

0 comments on commit 596206c

Please sign in to comment.