Skip to content

Commit

Permalink
feat: add getAcceptLanguage (#5)
Browse files Browse the repository at this point in the history
  • Loading branch information
kazupon authored Sep 22, 2023
1 parent 13151f9 commit 1e92327
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 26 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ You can do `import { ... } from '@intlify/utils'` the above utilities
### HTTP

- `getAcceptLanguages`
- `getAcceptLanguage`
- `getLocale`
- `getCookieLocale`
- `setCookieLocale`
Expand Down
91 changes: 67 additions & 24 deletions src/h3.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { beforeEach, describe, expect, test } from 'vitest'
import { createApp, eventHandler, toNodeListener } from 'h3'
import supertest from 'supertest'
import {
getAcceptLanguage,
getAcceptLanguages,
getCookieLocale,
getLocale,
Expand All @@ -14,7 +15,7 @@ import type { SuperTest, Test } from 'supertest'

describe('getAcceptLanguages', () => {
test('basic', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
Expand All @@ -24,11 +25,11 @@ describe('getAcceptLanguages', () => {
},
},
} as H3Event
expect(getAcceptLanguages(eventMock)).toEqual(['en-US', 'en', 'ja'])
expect(getAcceptLanguages(mockEvent)).toEqual(['en-US', 'en', 'ja'])
})

test('any language', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
Expand All @@ -38,25 +39,67 @@ describe('getAcceptLanguages', () => {
},
},
} as H3Event
expect(getAcceptLanguages(eventMock)).toEqual([])
expect(getAcceptLanguages(mockEvent)).toEqual([])
})

test('empty', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
headers: {},
},
},
} as H3Event
expect(getAcceptLanguages(eventMock)).toEqual([])
expect(getAcceptLanguages(mockEvent)).toEqual([])
})
})

describe('getAcceptLanguage', () => {
test('basic', () => {
const mockEvent = {
node: {
req: {
method: 'GET',
headers: {
'accept-language': 'en-US,en;q=0.9,ja;q=0.8',
},
},
},
} as H3Event
expect(getAcceptLanguage(mockEvent)).toEqual('en-US')
})

test('any language', () => {
const mockEvent = {
node: {
req: {
method: 'GET',
headers: {
'accept-language': '*',
},
},
},
} as H3Event
expect(getAcceptLanguage(mockEvent)).toEqual('')
})

test('empty', () => {
const mockEvent = {
node: {
req: {
method: 'GET',
headers: {},
},
},
} as H3Event
expect(getAcceptLanguage(mockEvent)).toEqual('')
})
})

describe('getLocale', () => {
test('basic', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
Expand All @@ -66,15 +109,15 @@ describe('getLocale', () => {
},
},
} as H3Event
const locale = getLocale(eventMock)
const locale = getLocale(mockEvent)

expect(locale.baseName).toEqual('en-US')
expect(locale.language).toEqual('en')
expect(locale.region).toEqual('US')
})

test('accept-language is any language', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
Expand All @@ -84,13 +127,13 @@ describe('getLocale', () => {
},
},
} as H3Event
const locale = getLocale(eventMock)
const locale = getLocale(mockEvent)

expect(locale.baseName).toEqual(DEFAULT_LANG_TAG)
})

test('specify default language', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
Expand All @@ -100,13 +143,13 @@ describe('getLocale', () => {
},
},
} as H3Event
const locale = getLocale(eventMock, 'ja-JP')
const locale = getLocale(mockEvent, 'ja-JP')

expect(locale.baseName).toEqual('ja-JP')
})

test('RangeError', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
Expand All @@ -117,13 +160,13 @@ describe('getLocale', () => {
},
} as H3Event

expect(() => getLocale(eventMock, 'ja-JP')).toThrowError(RangeError)
expect(() => getLocale(mockEvent, 'ja-JP')).toThrowError(RangeError)
})
})

describe('getCookieLocale', () => {
test('basic', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
Expand All @@ -133,43 +176,43 @@ describe('getCookieLocale', () => {
},
},
} as H3Event
const locale = getCookieLocale(eventMock)
const locale = getCookieLocale(mockEvent)

expect(locale.baseName).toEqual('ja-US')
expect(locale.language).toEqual('ja')
expect(locale.region).toEqual('US')
})

test('cookie is empty', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
headers: {},
},
},
} as H3Event
const locale = getCookieLocale(eventMock)
const locale = getCookieLocale(mockEvent)

expect(locale.baseName).toEqual(DEFAULT_LANG_TAG)
})

test('specify default language', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
headers: {},
},
},
} as H3Event
const locale = getCookieLocale(eventMock, { lang: 'ja-JP' })
const locale = getCookieLocale(mockEvent, { lang: 'ja-JP' })

expect(locale.baseName).toEqual('ja-JP')
})

test('specify cookie name', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
Expand All @@ -179,13 +222,13 @@ describe('getCookieLocale', () => {
},
},
} as H3Event
const locale = getCookieLocale(eventMock, { name: 'intlify_locale' })
const locale = getCookieLocale(mockEvent, { name: 'intlify_locale' })

expect(locale.baseName).toEqual('fr-FR')
})

test('RangeError', () => {
const eventMock = {
const mockEvent = {
node: {
req: {
method: 'GET',
Expand All @@ -196,7 +239,7 @@ describe('getCookieLocale', () => {
},
} as H3Event

expect(() => getCookieLocale(eventMock, { name: 'intlify_locale' }))
expect(() => getCookieLocale(mockEvent, { name: 'intlify_locale' }))
.toThrowError(RangeError)
})
})
Expand Down
11 changes: 11 additions & 0 deletions src/h3.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,17 @@ export function getAcceptLanguages(event: H3Event): string[] {
return getAcceptLanguagesWithGetter(getter)
}

/**
* get accept language
*
* @param {H3Event} event The {@link H3Event | H3} event
*
* @returns {string} The **first language tag** of `accept-language` header, if `accept-language` header is not exists, or `*` (any language), return empty string.
*/
export function getAcceptLanguage(event: H3Event): string {
return getAcceptLanguages(event)[0] || ''
}

/**
* get locale
*
Expand Down
28 changes: 28 additions & 0 deletions src/node.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { describe, expect, test } from 'vitest'
import supertest from 'supertest'
import {
getAcceptLanguage,
getAcceptLanguages,
getCookieLocale,
getLocale,
Expand Down Expand Up @@ -36,6 +37,33 @@ describe('getAcceptLanguages', () => {
})
})

describe('getAcceptLanguage', () => {
test('basic', () => {
const mockRequest = {
headers: {
'accept-language': 'en-US,en;q=0.9,ja;q=0.8',
},
} as IncomingMessage
expect(getAcceptLanguage(mockRequest)).toBe('en-US')
})

test('any language', () => {
const mockRequest = {
headers: {
'accept-language': '*',
},
} as IncomingMessage
expect(getAcceptLanguage(mockRequest)).toBe('')
})

test('empty', () => {
const mockRequest = {
headers: {},
} as IncomingMessage
expect(getAcceptLanguage(mockRequest)).toBe('')
})
})

describe('getLocale', () => {
test('basic', () => {
const mockRequest = {
Expand Down
13 changes: 12 additions & 1 deletion src/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,22 @@ import type { CookieOptions } from './http.ts'
*
* @returns {Array<string>} The array of language tags, if `*` (any language) or empty string is detected, return an empty array.
*/
export function getAcceptLanguages(req: IncomingMessage) {
export function getAcceptLanguages(req: IncomingMessage): string[] {
const getter = () => req.headers['accept-language']
return getAcceptLanguagesWithGetter(getter)
}

/**
* get accept language
*
* @param {IncomingMessage} request The {@link IncomingMessage | request}
*
* @returns {string} The **first language tag** of `accept-language` header, if `accept-language` header is not exists, or `*` (any language), return empty string.
*/
export function getAcceptLanguage(req: IncomingMessage): string {
return getAcceptLanguages(req)[0] || ''
}

/**
* get locale
*
Expand Down
20 changes: 20 additions & 0 deletions src/web.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { describe, expect, test } from 'vitest'
import {
getAcceptLanguage,
getAcceptLanguages,
getCookieLocale,
getLocale,
Expand All @@ -26,6 +27,25 @@ describe('getAcceptLanguages', () => {
})
})

describe('getAcceptLanguage', () => {
test('basic', () => {
const mockRequest = new Request('https://example.com')
mockRequest.headers.set('accept-language', 'en-US,en;q=0.9,ja;q=0.8')
expect(getAcceptLanguage(mockRequest)).toBe('en-US')
})

test('any language', () => {
const mockRequest = new Request('https://example.com')
mockRequest.headers.set('accept-language', '*')
expect(getAcceptLanguage(mockRequest)).toBe('')
})

test('empty', () => {
const mockRequest = new Request('https://example.com')
expect(getAcceptLanguage(mockRequest)).toBe('')
})
})

describe('getLocale', () => {
test('basic', () => {
const mockRequest = new Request('https://example.com')
Expand Down
13 changes: 12 additions & 1 deletion src/web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,22 @@ import type { CookieOptions } from './http.ts'
*
* @returns {Array<string>} The array of language tags, if `*` (any language) or empty string is detected, return an empty array.
*/
export function getAcceptLanguages(req: Request) {
export function getAcceptLanguages(req: Request): string[] {
const getter = () => req.headers.get('accept-language')
return getAcceptLanguagesWithGetter(getter)
}

/**
* get accept language
*
* @param {Request} request The {@link Request | request}
*
* @returns {string} The **first language tag** of `accept-language` header, if `accept-language` header is not exists, or `*` (any language), return empty string.
*/
export function getAcceptLanguage(req: Request): string {
return getAcceptLanguages(req)[0] || ''
}

/**
* get locale
*
Expand Down

0 comments on commit 1e92327

Please sign in to comment.