Skip to content

Commit 41b5851

Browse files
committed
refactor: Localization
BREAKING CHANGE: Removed `getLocale` and `Locale` - Rename `Locale` to `L10nEngine` - Rename `Locale.getLocaleStr` to `Locale.getTemplate` - Rename `getLocale` to `createL10n`
1 parent ab39c60 commit 41b5851

File tree

6 files changed

+58
-44
lines changed

6 files changed

+58
-44
lines changed

core/src/__tests__/locale.spec.ts

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { getLocale } from '@/locale'
1+
import { createL10n } from '@/locale'
22
import { FieldPattern, TextPosition } from '@/types'
33
import { describe, expect, it } from 'vitest'
44

55
describe('locale', () => {
6-
it('getLocale', () => {
6+
it('createL10n', () => {
77
const testCases = [
88
{ locale: 'en', expected: 'Hour' },
99
{ locale: 'foo-bar', expected: 'Hour' },
@@ -13,43 +13,43 @@ describe('locale', () => {
1313
]
1414

1515
for (const test of testCases) {
16-
const l = getLocale(test.locale)
17-
expect(l.getLocaleStr('hour', 'text')).toBe(test.expected)
16+
const l = createL10n(test.locale)
17+
expect(l.getTemplate('hour', 'text')).toBe(test.expected)
1818
}
1919
})
2020

21-
it('getLocaleStr', () => {
22-
const l = getLocale('en', {
21+
it('getTemplate', () => {
22+
const l = createL10n('en', {
2323
custom: {
2424
'*': 'bar',
2525
message: 'baz',
2626
},
2727
})
2828

29-
expect(l.getLocaleStr('year', 'minute', 'empty', 'text')).toBe('every {{field.id}}')
30-
expect(l.getLocaleStr('year', 'dayOfWeek', 'value', 'prefix')).toBe('and')
31-
expect(l.getLocaleStr('year', 'minute', 'range', 'prefix')).toBe(':')
32-
expect(l.getLocaleStr('custom', 'foo')).toBe('bar')
33-
expect(l.getLocaleStr('custom', 'message')).toBe('baz')
29+
expect(l.getTemplate('year', 'minute', 'any', 'text')).toBe('every {{field.id}}')
30+
expect(l.getTemplate('year', 'dayOfWeek', 'value', 'prefix')).toBe('and')
31+
expect(l.getTemplate('year', 'minute', 'range', 'prefix')).toBe(':')
32+
expect(l.getTemplate('custom', 'foo')).toBe('bar')
33+
expect(l.getTemplate('custom', 'message')).toBe('baz')
3434
})
3535

36-
it('getLocaleStr pt', () => {
37-
const l = getLocale('pt', {
36+
it('getTemplate pt', () => {
37+
const l = createL10n('pt', {
3838
custom: {
3939
'*': 'bar',
4040
message: 'baz',
4141
},
4242
})
4343

44-
expect(l.getLocaleStr('year', 'minute', 'empty', 'text')).toBe('cada minuto')
45-
expect(l.getLocaleStr('year', 'dayOfWeek', 'value', 'prefix')).toBe('e de')
46-
expect(l.getLocaleStr('year', 'minute', 'range', 'prefix')).toBe(':')
47-
expect(l.getLocaleStr('custom', 'foo')).toBe('bar')
48-
expect(l.getLocaleStr('custom', 'message')).toBe('baz')
44+
expect(l.getTemplate('year', 'minute', 'any', 'text')).toBe('cada minuto')
45+
expect(l.getTemplate('year', 'dayOfWeek', 'value', 'prefix')).toBe('e de')
46+
expect(l.getTemplate('year', 'minute', 'range', 'prefix')).toBe(':')
47+
expect(l.getTemplate('custom', 'foo')).toBe('bar')
48+
expect(l.getTemplate('custom', 'message')).toBe('baz')
4949
})
5050

5151
it('render', () => {
52-
const l = getLocale('en', {
52+
const l = createL10n('en', {
5353
'*': {
5454
'*': {
5555
value: {

core/src/components/__tests__/cron-segment.spec.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { describe, expect, it } from 'vitest'
22

3-
import { getLocale } from '@/locale'
3+
import { createL10n } from '@/locale'
44
import { FieldWrapper } from '@/types'
55
import { defaultItems } from '@/util'
66
import { nextTick, ref } from 'vue'
@@ -15,7 +15,7 @@ const f = () => {
1515
const period = { id: 'year', value: [] }
1616

1717
return useCronSegment({
18-
locale: getLocale('en'),
18+
l10n: createL10n('en'),
1919
field: fieldDesc,
2020
period: ref(period),
2121
initialCron: '*',

core/src/components/cron-core.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { AnySegment, NoSpecificSegment, RangeSegment, StepSegment, ValueSegment } from '@/cron'
2+
import { createL10n } from '@/locale'
23
import type { Localization } from '@/locale/types'
34
import {
45
computed,
@@ -9,7 +10,6 @@ import {
910
type PropType,
1011
type SetupContext,
1112
} from 'vue'
12-
import { getLocale } from '../locale'
1313
import { FieldWrapper, TextPosition, type CronFormat, type Field, type Period } from '../types'
1414
import { defaultItems } from '../util'
1515
import { useCronSegment, type UseCronSegmentReturn } from './cron-segment'
@@ -142,11 +142,11 @@ export function useCron(options: CronOptions) {
142142
const { customLocale, fields = cronDefaults.fields(format, locale) } = options
143143
const initialValue = options.initialValue ?? cronDefaults.initialValue(fields.length)
144144

145-
const l10n = getLocale(locale, customLocale)
145+
const l10n = createL10n(locale, customLocale)
146146
const periods = (options.periods ?? cronDefaults.periods(format)).map((p) => {
147147
return {
148148
...p,
149-
text: p.text ?? l10n.getLocaleStr(p.id, TextPosition.Text),
149+
text: p.text ?? l10n.getTemplate(p.id, TextPosition.Text),
150150
}
151151
})
152152
const initialPeriod =
@@ -160,7 +160,7 @@ export function useCron(options: CronOptions) {
160160
const periodPrefix = ref('')
161161
const periodSuffix = ref('')
162162
const segments = fields.map((f) => {
163-
return useCronSegment({ field: new FieldWrapper(f), locale: l10n, period })
163+
return useCronSegment({ field: new FieldWrapper(f), l10n, period })
164164
})
165165

166166
const segmentMap = new Map(segments.map((s) => [s.id, s]))
@@ -205,8 +205,8 @@ export function useCron(options: CronOptions) {
205205
}
206206

207207
const translate = () => {
208-
periodPrefix.value = l10n.getLocaleStr(period.value.id, TextPosition.Prefix)
209-
periodSuffix.value = l10n.getLocaleStr(period.value.id, TextPosition.Suffix)
208+
periodPrefix.value = l10n.getTemplate(period.value.id, TextPosition.Prefix)
209+
periodSuffix.value = l10n.getTemplate(period.value.id, TextPosition.Suffix)
210210
}
211211
translate()
212212

core/src/components/cron-segment.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
import { CombinedSegment, arrayToSegment, cronToSegment } from '@/cron'
2-
import type { Locale } from '@/locale'
2+
import type { L10nEngine } from '@/locale'
33
import { TextPosition, type CronSegment, type FieldWrapper, type Period } from '@/types'
44
import { ref, watch, type Ref } from 'vue'
55

66
export interface FieldOptions {
7-
locale: Locale
7+
l10n: L10nEngine
88
period: Ref<Period>
99
field: FieldWrapper
1010
initialCron?: string
1111
}
1212

1313
export function useCronSegment(options: FieldOptions) {
14-
const { period, field, initialCron = '*', locale } = options
14+
const { period, field, initialCron = '*', l10n } = options
1515

1616
const cron = ref(initialCron)
1717
const error = ref('')
@@ -26,15 +26,15 @@ export function useCronSegment(options: FieldOptions) {
2626

2727
text.value = segments
2828
.map((seg) => {
29-
return locale.render(period.value.id, field.id, seg.type, TextPosition.Text, {
29+
return l10n.render(period.value.id, field.id, seg.type, TextPosition.Text, {
3030
field: field,
3131
...seg.items,
3232
})
3333
})
3434
.join(',')
3535

36-
prefix.value = locale.getLocaleStr(period.value.id, field.id, seg.type, TextPosition.Prefix)
37-
suffix.value = locale.getLocaleStr(period.value.id, field.id, seg.type, TextPosition.Suffix)
36+
prefix.value = l10n.getTemplate(period.value.id, field.id, seg.type, TextPosition.Prefix)
37+
suffix.value = l10n.getTemplate(period.value.id, field.id, seg.type, TextPosition.Suffix)
3838
}
3939

4040
const parseCron = (cron: string) => {

core/src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export {
1919
type SelectOptions,
2020
type UseSelectReturn,
2121
} from './components/select'
22-
export { Locale, getLocale } from './locale'
22+
export { createL10n, L10nEngine } from './locale'
2323
export type * from './locale/types'
2424
export type * from './types'
2525
export { FieldPattern, FieldWrapper, TextPosition } from './types'

core/src/locale/index.ts

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,45 +31,59 @@ const locales: Record<string, Localization> = {
3131
ko,
3232
}
3333

34-
class Locale {
34+
class L10nEngine {
3535
dict: Localization
3636

3737
constructor(dict: Localization) {
3838
this.dict = dict
3939
}
4040

41-
getLocaleStr(...keys: string[]) {
41+
/**
42+
* Gets a localization template by traversing the dictionary using provided keys.
43+
* @param keys - Array of keys to traverse through the localization dictionary
44+
* @returns The found template string or empty string if not found
45+
*/
46+
getTemplate(...keys: string[]) {
4247
const k = keys.map((key) => [key, '*'])
4348
return traverse(this.dict, ...k) || ''
4449
}
4550

51+
/**
52+
* Renders a localization template with the provided parameters using Mustache.
53+
* @param periodId - The period identifier (e.g. 'year', 'month')
54+
* @param fieldId - The field identifier (e.g. 'hour', 'minute')
55+
* @param fieldPattern - The pattern type of the field
56+
* @param position - The text position
57+
* @param params - Parameters to be interpolated into the template
58+
* @returns The rendered localization string
59+
*/
4660
render(
4761
periodId: string,
4862
fieldId: string,
4963
fieldPattern: FieldPattern,
5064
position: TextPosition,
5165
params: any,
5266
) {
53-
const template = this.getLocaleStr(periodId, fieldId, fieldPattern, position)
67+
const template = this.getTemplate(periodId, fieldId, fieldPattern, position)
5468
return Mustache.render(template, params || {})
5569
}
5670
}
5771

5872
/**
59-
*
60-
* @param locale - locale code, e.g.: en, en-GB de-DE
61-
* @param mixin - can be used to override values of the Locale
62-
* @returns {Locale} Dictionary with all strings in the requested language
73+
* Creates a localization engine for the specified locale.
74+
* @param localeCode - Locale code (e.g. 'en', 'en-GB', 'de-DE')
75+
* @param mixin - Optional dictionary to override default locale strings
76+
* @returns A new L10nEngine instance for the specified locale with English as fallback
6377
*/
64-
function getLocale(localeCode: string, mixin?: Localization) {
78+
function createL10n(localeCode: string, mixin?: Localization) {
6579
const [language] = localeCode.split('-')
6680
const l = locales[localeCode.toLowerCase()] || locales[language.toLowerCase()] || locales.en
6781
// Note: always use an empty object as target
6882
const dict = deepMerge({}, locales.en, l, mixin || {}) as Localization
69-
return new Locale(dict)
83+
return new L10nEngine(dict)
7084
}
7185

72-
export { getLocale, Locale }
86+
export { createL10n, L10nEngine }
7387

7488
// The following prompt was used for localizations translated with GPT-4:
7589
//

0 commit comments

Comments
 (0)