Skip to content

Commit

Permalink
feat: improve localization interface
Browse files Browse the repository at this point in the history
  • Loading branch information
ayZagen committed Dec 4, 2024
1 parent df01e8f commit d997327
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 42 deletions.
29 changes: 12 additions & 17 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import deepmerge from 'deepmerge';
import type { App } from 'vue';
import { reactive } from 'vue';

import defaultDictionary from './i18n'
import { createTranslator, createWidget } from './ui';
import { createWidget } from './ui';
import type { IPlusAuthContext, IWidgetSettings } from './ui/interfaces';
import type { FetchWrapper } from './ui/utils/fetch';
import { createFetchWrapper } from './ui/utils/fetch';
import type { Translator } from './ui/utils/translator';
import { Translator } from './ui/utils/translator';

export default class PlusAuthWidget {
private _view: App<Element>;
Expand All @@ -22,21 +20,18 @@ export default class PlusAuthWidget {

this.http = createFetchWrapper(settings.apiUrl)

const { locale: localeSettings, ...otherSettings } = settings
const reactiveSettings = reactive(settings)

const reactiveSettings = reactive(
deepmerge({
locale: {
defaultLocale: localeSettings?.defaultLocale || 'en',
selectedLocale: localeSettings?.selectedLocale || context.params?.ui_locale,
dictionary: deepmerge(defaultDictionary, localeSettings?.dictionary || {})
this.i18n = new Translator(reactiveSettings.locale)
if(context.params?.ui_locales){
const userPreferredLocales = context.params?.ui_locales?.split(' ') || []
for (let contextLocale of userPreferredLocales) {
if(this.i18n.locales[contextLocale]){
this.i18n.locale = contextLocale
break;
}
},
otherSettings,
{ clone: true })
)

this.i18n = createTranslator(reactiveSettings.locale)
}
}
this._view = createWidget(container || document.body, reactiveSettings as any, context, {
i18n: this.i18n,
http: this.http,
Expand Down
11 changes: 6 additions & 5 deletions src/ui/components/Footer.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<template>
<footer>
<template v-if="languages && languages.length">
<template v-if="languages && languages.length > 1">
<PSelect
v-model="translator.locale"
flat
label="Language"
style="width: auto; margin: 0"
dense
hide-messages
item-text="label"
:items="languages"
/>
</template>
Expand Down Expand Up @@ -38,9 +39,10 @@
</template>

<script lang="ts">
import { defineComponent, inject, reactive } from 'vue';
import { defineComponent, inject } from 'vue';
import type { IPlusAuthContext } from '../interfaces';
import type { Translator } from '../utils/translator';
import { translatorKey } from '../utils/translator';
export default defineComponent({
Expand All @@ -57,12 +59,11 @@ export default defineComponent({
},
setup(){
const context = inject('context') as IPlusAuthContext
const translator = inject(translatorKey) as any
const translator = inject(translatorKey) as Translator
const client = context.client
const languages = reactive(context.ui_locales || [])
return {
translator,
languages,
languages: Object.values(translator.locales || []),
tosUri: client.tosUri,
policyUri: client.policyUri,
}
Expand Down
10 changes: 1 addition & 9 deletions src/ui/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,12 @@ import { Theme } from './utils/theme';
import { Translator, translatorKey } from './utils/translator';
import { App } from './widget';

export function createTranslator(settings: IWidgetSettings['locale']) {
return new Translator(
settings.dictionary,
settings.defaultLocale,
settings.selectedLocale
)
}

export function createWidget(container: Element | string,
settings: IWidgetSettings,
context: Partial<IPlusAuthContext>,
inject) {
const theme = new Theme(settings.theme);
const translator = inject.i18n || createTranslator(settings.locale)
const translator = inject.i18n || new Translator(settings.locale)
const widget = createApp(App(theme, settings));

widget.directive('t', i18n)
Expand Down
4 changes: 2 additions & 2 deletions src/ui/interfaces/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export interface IClient {

type DictionaryItem = string | Record<string, any>
export interface ILocaleSettings {
locales?: Record<string, { label: string, codes: string[] }>
dictionary: Record<string, typeof defaultDictionary | DictionaryItem>;
defaultLocale: string;
selectedLocale?: string;
Expand Down Expand Up @@ -189,8 +190,7 @@ export interface IPlusAuthContext {
prompt?: {
name: string,
mode?: string
},
ui_locales: string[]
}
}

export type ITranslatePath = string | {
Expand Down
33 changes: 24 additions & 9 deletions src/ui/utils/translator.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,44 @@
import deepmerge from 'deepmerge';
import type { Ref } from 'vue';
import { getCurrentInstance } from 'vue';
import { ref } from 'vue';

import defaultDictionary from '../../i18n'

import type { ILocaleSettings } from '../interfaces';

import { escapeRegExp, isObject, keysToDotNotation, propertyAccessor } from '.';

export const translatorKey = Symbol('t')


export class Translator {
private fallBackLocale: string;
private defaultLocale: string;
private dictionary: any;
private selectedLocale: Ref
locales: Record<string, { label: string, codes: string[], value: string }>

constructor(dictionary: any, fallbackLocale?: string, selectedLocale?: string) {
this.dictionary = dictionary;
this.fallBackLocale = fallbackLocale || 'en'
this.selectedLocale = ref<string | undefined>(selectedLocale || this.fallBackLocale)
constructor(options: Partial<ILocaleSettings> = {}) {
this.dictionary = deepmerge(defaultDictionary, options.dictionary || {});
this.defaultLocale = options.defaultLocale = options.defaultLocale || 'en'
this.selectedLocale = ref<string | undefined>(options.selectedLocale || this.defaultLocale)
this.locales = Object.keys(this.dictionary).reduce((finalLocales, dictKey) => {
finalLocales[dictKey] = options.locales?.[dictKey] || { label: dictKey, codes: [dictKey] }
finalLocales[dictKey].value = dictKey
return finalLocales
}, {})
}

get localeRef() {
return this.selectedLocale
}

set locale(locale: string) {
this.selectedLocale.value = locale
if (this.locales[locale]) {
this.selectedLocale.value = locale
} else {
this.selectedLocale.value = this.defaultLocale
}
}

get locale(): string {
Expand Down Expand Up @@ -51,7 +66,7 @@ export class Translator {
}
const locale = opts.locale || this.locale
const value = propertyAccessor(vm.dictionary[locale], key)
|| propertyAccessor(vm.dictionary[vm.fallBackLocale], key);
|| propertyAccessor(vm.dictionary[vm.defaultLocale], key);
if (value) {
return vm._interpolate(
value,
Expand All @@ -61,7 +76,7 @@ export class Translator {
} else if (opts.fallback) {
return vm._interpolate(
propertyAccessor(vm.dictionary[locale], opts.fallback)
|| propertyAccessor(vm.dictionary[vm.fallBackLocale], opts.fallback)
|| propertyAccessor(vm.dictionary[vm.defaultLocale], opts.fallback)
|| opts.fallback,
params,
locale
Expand All @@ -83,7 +98,7 @@ export class Translator {
str = str.replace(searchRegexp,
v === null ||
v === undefined ? '' : propertyAccessor(this.dictionary[locale], v)
|| propertyAccessor(this.dictionary[this.fallBackLocale], v)
|| propertyAccessor(this.dictionary[this.defaultLocale], v)
|| v
)
})
Expand Down

0 comments on commit d997327

Please sign in to comment.