You've already forked AstralRinth
forked from didirus/AstralRinth
Add the language setting page (#1210)
* Add initial language picker prototype * Heap o' improvements and Pirate tongue * Move .visually-hidden to shared utils and add copyright notice * Add a little space before categories names * Simplify search to input focus logic * Remove larger font size and padding from the search field * Some refactors * Braw's descent into madness Thanks web development! In seriousness though, tried to make the list more accessible. Making it fully accessible feels like unbearable task, so at least that. * Litol refactoring * Extract new strings and remove old ones * Update @vintl/nuxt to 1.3.0 This fixes the bug where default locale won't be saved. * A buncha refactorings and cleanup * Scuttle the Pirate lingo 'Twas employed 'ere for testin' purposes, but fear not, for it shall be returnin' in the days to come. Should ye require it fer testin', simply roll back this here commit. * Clean languages source file * Change "US" to "United States" I think it would make distinguishing two languages simpler as now there's more than one letter of difference (US/UK vs United States/ United Kingdom).
This commit is contained in:
13
composables/auto-ref.ts
Normal file
13
composables/auto-ref.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
export type AutoRef<T> = [T] extends [(...args: any[]) => any]
|
||||
? Ref<T> | (() => T)
|
||||
: T | Ref<T> | (() => T)
|
||||
|
||||
/**
|
||||
* Accepts a value directly, a ref with the value or a getter function and returns a Vue ref.
|
||||
* @param value The value to use.
|
||||
* @returns Either the original or newly created ref.
|
||||
*/
|
||||
export function useAutoRef<T>(value: AutoRef<T>): Ref<T> {
|
||||
if (typeof value === 'function') return computed(() => value())
|
||||
return isRef(value) ? value : ref(value as any)
|
||||
}
|
||||
91
composables/display-names.ts
Normal file
91
composables/display-names.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import { useAutoRef, type AutoRef } from './auto-ref.ts'
|
||||
|
||||
const safeTags = new Map<string, string>()
|
||||
|
||||
function safeTagFor(locale: string) {
|
||||
let safeTag = safeTags.get(locale)
|
||||
if (safeTag == null) {
|
||||
safeTag = new Intl.Locale(locale).baseName
|
||||
safeTags.set(locale, safeTag)
|
||||
}
|
||||
return safeTag
|
||||
}
|
||||
|
||||
type DisplayNamesWrapper = Intl.DisplayNames & {
|
||||
of(tag: string): string | undefined
|
||||
}
|
||||
|
||||
const displayNamesDicts = new Map<string, DisplayNamesWrapper>()
|
||||
|
||||
function getWrapperKey(locale: string, options: Intl.DisplayNamesOptions) {
|
||||
return JSON.stringify({ ...options, locale })
|
||||
}
|
||||
|
||||
export function createDisplayNames(
|
||||
locale: string,
|
||||
options: Intl.DisplayNamesOptions = { type: 'language' }
|
||||
) {
|
||||
const wrapperKey = getWrapperKey(locale, options)
|
||||
let wrapper = displayNamesDicts.get(wrapperKey)
|
||||
|
||||
if (wrapper == null) {
|
||||
const dict = new Intl.DisplayNames(locale, options)
|
||||
|
||||
const badTags: string[] = []
|
||||
|
||||
wrapper = {
|
||||
resolvedOptions() {
|
||||
return dict.resolvedOptions()
|
||||
},
|
||||
of(tag: string) {
|
||||
let attempt = 0
|
||||
|
||||
// eslint-disable-next-line no-labels
|
||||
lookupLoop: do {
|
||||
let lookup: string
|
||||
switch (attempt) {
|
||||
case 0:
|
||||
lookup = tag
|
||||
break
|
||||
case 1:
|
||||
lookup = safeTagFor(tag)
|
||||
break
|
||||
default:
|
||||
// eslint-disable-next-line no-labels
|
||||
break lookupLoop
|
||||
}
|
||||
|
||||
if (badTags.includes(lookup)) continue
|
||||
|
||||
try {
|
||||
return dict.of(lookup)
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
`Failed to get display name for ${lookup} using dictionary for ${
|
||||
this.resolvedOptions().locale
|
||||
}`
|
||||
)
|
||||
badTags.push(lookup)
|
||||
continue
|
||||
}
|
||||
} while (++attempt < 5)
|
||||
|
||||
return undefined
|
||||
},
|
||||
}
|
||||
|
||||
displayNamesDicts.set(wrapperKey, wrapper)
|
||||
}
|
||||
|
||||
return wrapper
|
||||
}
|
||||
|
||||
export function useDisplayNames(
|
||||
locale: AutoRef<string>,
|
||||
options?: AutoRef<Intl.DisplayNamesOptions | undefined>
|
||||
) {
|
||||
const $locale = useAutoRef(locale)
|
||||
const $options = useAutoRef(options)
|
||||
|
||||
return computed(() => createDisplayNames($locale.value, $options.value))
|
||||
}
|
||||
Reference in New Issue
Block a user