File size: 2,480 Bytes
dbb1bf9 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | import { getCurrentLanguage } from '@/services/i18n';
const LANG_TO_TILE_FIELD: Record<string, string> = {
en: 'name:en',
bg: 'name:bg',
cs: 'name:cs',
fr: 'name:fr',
de: 'name:de',
el: 'name:el',
es: 'name:es',
hr: 'name:hr',
hu: 'name:hu',
it: 'name:it',
pl: 'name:pl',
pt: 'name:pt',
nl: 'name:nl',
sv: 'name:sv',
ru: 'name:ru',
ar: 'name:ar',
zh: 'name:zh',
ja: 'name:ja',
ko: 'name:ko',
ro: 'name:ro',
tr: 'name:tr',
th: 'name:th',
hi: 'name:hi',
// vi — not available in Protomaps/OSM tiles
};
type Expression = [string, ...unknown[]];
interface MapStyleLayer {
id: string;
type?: string;
}
interface MapStyle {
layers?: MapStyleLayer[];
}
interface LocalizableMap {
getStyle?: () => MapStyle | null | undefined;
getLayoutProperty?: (layerId: string, property: 'text-field') => unknown;
setLayoutProperty?: (layerId: string, property: 'text-field', value: Expression) => void;
}
export function getLocalizedNameField(lang?: string): string {
const code = lang ?? getCurrentLanguage();
return LANG_TO_TILE_FIELD[code] ?? 'name:en';
}
export function getLocalizedNameExpression(lang?: string): Expression {
const field = getLocalizedNameField(lang);
if (field === 'name:en') {
return ['coalesce', ['get', 'name:en'], ['get', 'name']];
}
return ['coalesce', ['get', field], ['get', 'name:en'], ['get', 'name']];
}
export function isLocalizableTextField(textField: unknown): boolean {
if (!textField) return false;
if (typeof textField === 'string') {
return /\{name[^}]*\}/.test(textField);
}
if (typeof textField === 'object') {
const s = JSON.stringify(textField);
const hasName =
s.includes('"name"') ||
s.includes('"name:') ||
s.includes('"name_en"') ||
s.includes('"name_int"') ||
s.includes('{name');
return hasName;
}
return false;
}
export function localizeMapLabels(map: LocalizableMap | null | undefined): void {
if (!map) return;
const style = map?.getStyle?.();
if (!style?.layers) return;
const expr = getLocalizedNameExpression();
for (const layer of style.layers) {
if (layer.type !== 'symbol') continue;
let textField: unknown;
try {
textField = map.getLayoutProperty?.(layer.id, 'text-field');
} catch {
continue;
}
if (!isLocalizableTextField(textField)) continue;
try {
map.setLayoutProperty?.(layer.id, 'text-field', expr);
} catch {}
}
}
|