forked from FOSS/BangleApps
locale: Improve handling of non-ASCII characters (fix #469)
parent
30ae2f65f5
commit
d9442f2fd0
|
@ -65,7 +65,7 @@
|
|||
{ "id": "locale",
|
||||
"name": "Languages",
|
||||
"icon": "locale.png",
|
||||
"version":"0.06",
|
||||
"version":"0.07",
|
||||
"description": "Translations for different countries",
|
||||
"tags": "tool,system,locale,translate",
|
||||
"type": "locale",
|
||||
|
|
|
@ -6,3 +6,4 @@
|
|||
Add correct scaling for speed/distance/temperature
|
||||
0.06: Remove translations if not required
|
||||
Ensure 'on' is always supplied for translations
|
||||
0.07: Improve handling of non-ASCII characters (fix #469)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="../../css/spectre.min.css">
|
||||
</head>
|
||||
<body>
|
||||
|
@ -12,7 +13,7 @@
|
|||
<p>Then click <button id="upload" class="btn btn-primary">Upload</button></p>
|
||||
|
||||
<script src="../../lib/customize.js"></script>
|
||||
<script src="locales.js"></script>
|
||||
<script src="locales.js" charset="utf-8"></script>
|
||||
|
||||
<script>
|
||||
/*
|
||||
|
@ -45,7 +46,23 @@ exports = { name : "en_GB", currencySym:"£",
|
|||
};
|
||||
|
||||
*/
|
||||
|
||||
function codePageLookup(lang, codePage, ch) {
|
||||
var chCode = ch.charCodeAt();
|
||||
if (chCode>=32 && chCode<128) return ch; // ASCII - copy it
|
||||
// not normal ASCII
|
||||
var n; // default is a space
|
||||
if (codePage.map.indexOf(ch)>=0) // look up in char map, escape that
|
||||
n = 128+codePage.map.indexOf(ch);
|
||||
/*else if (chCode<256) // it's non-ascii, but <256 - just escape it
|
||||
n = chCode;*/
|
||||
else {
|
||||
if (charFallbacks[ch]) return charFallbacks[ch];
|
||||
console.error(`Locale ${lang}: Character ${ch} (${chCode}) is not in Code Page ${codePage.name}`);
|
||||
return undefined;
|
||||
}
|
||||
// escape the char
|
||||
return '\\x'+(n+256).toString(16).substr(-2);
|
||||
}
|
||||
|
||||
// do some sanity checks
|
||||
Object.keys(locales).forEach(function(localeName) {
|
||||
|
@ -54,6 +71,22 @@ exports = { name : "en_GB", currencySym:"£",
|
|||
if (distanceUnits[locale.distance[0]]===undefined) console.error(localeName+": Unknown distance unit "+locale.distance[0]);
|
||||
if (distanceUnits[locale.distance[1]]===undefined) console.error(localeName+": Unknown distance unit "+locale.distance[1]);
|
||||
if (speedUnits[locale.speed]===undefined) console.error(localeName+": Unknown speed unit "+locale.speed);
|
||||
if (locale.temperature!='°C' && locale.temperature!='°F')
|
||||
console.error(localeName+": Unknown temperature unit "+locale.temperature);
|
||||
// Now check that codepage is ok and all chars in translation are in that codepage
|
||||
const codePageName = "ISO8859-1";
|
||||
if (locale.codePage) codePageName = locale.codePage;
|
||||
const codePage = codePages[codePageName];
|
||||
if (codePage===undefined) console.error(localeName+": Unknown codePage "+codePageName);
|
||||
function checkChars(v,path) {
|
||||
if ("object"==typeof v)
|
||||
Object.keys(v).forEach(k=>checkChars(v[k], path+"."+k));
|
||||
else if ("string"==typeof v)
|
||||
for (var i=0;i<v.length;i++)
|
||||
if (codePageLookup(localeName, codePage, v[i])===undefined)
|
||||
console.error(` ... in ${path}[${i}]`);
|
||||
}
|
||||
checkChars(locale,localeName);
|
||||
});
|
||||
|
||||
var languageSelector = document.getElementById("languages");
|
||||
|
@ -68,17 +101,37 @@ exports = { name : "en_GB", currencySym:"£",
|
|||
|
||||
document.getElementById("upload").addEventListener("click", function() {
|
||||
|
||||
var lang = languageSelector.options[languageSelector.selectedIndex].value;
|
||||
console.log(lang);
|
||||
const lang = languageSelector.options[languageSelector.selectedIndex].value;
|
||||
console.log(`Language ${lang}`);
|
||||
|
||||
locale = locales[lang];
|
||||
const locale = locales[lang];
|
||||
if (!locale) {
|
||||
alert("Language not found!");
|
||||
alert(`Language ${lang} not found!`);
|
||||
return;
|
||||
}
|
||||
|
||||
const codePageName = "ISO8859-1";
|
||||
if (locale.codePage)
|
||||
codePageName = locale.codePage;
|
||||
const codePage = codePages[codePageName];
|
||||
if (!codePage) {
|
||||
alert(`Code Page ${codePageName} not found!`);
|
||||
return;
|
||||
}
|
||||
|
||||
function js(x) { return JSON.stringify(x); }
|
||||
// Convert object to JSON, with codepage
|
||||
function js(x) {
|
||||
// do nortmal conversion
|
||||
x = JSON.stringify(x);
|
||||
/* assume any out of bounds character is going to
|
||||
be inside a quoted string */
|
||||
var s = '';
|
||||
for (var i=0;i<x.length;i++) {
|
||||
var ch = codePageLookup(lang, codePage, x[i]);
|
||||
s += (ch===undefined) ? "?" : ch;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
var replaceList = {
|
||||
"%Y": "d.getFullYear()",
|
||||
|
@ -116,7 +169,7 @@ exports = { name : "en_GB", currencySym:"£",
|
|||
else if (locale.temperature=='°F') temperature="(t*9/5)+32";
|
||||
else throw new Error("Unknown temperature unit "+locale.temperature);
|
||||
|
||||
var localeModule = `var l = ${JSON.stringify({
|
||||
var localeModule = `var l = ${js({
|
||||
abday : locale.abday,
|
||||
day : locale.day,
|
||||
abmonth : locale.abmonth,
|
||||
|
|
|
@ -13,6 +13,34 @@ const speedUnits = { // how many kph per X?
|
|||
"mph": 1.60934
|
||||
};
|
||||
|
||||
/*
|
||||
For a codepage, 'map' is a map of char codes 128 and above.
|
||||
Where there is no character, just use '.'
|
||||
*/
|
||||
const codePages = {
|
||||
"ISO8859-1" : {
|
||||
name : "ISO8859-1",
|
||||
map : `
|
||||
€.‚ƒ„…†‡ˆ‰Š‹Œ.Ž.
|
||||
.‘’“”•–—˜™š›œ.žŸ
|
||||
.¡¢£¤¥¦§¨©ª«¬.®¯
|
||||
°±²³´µ¶·¸¹º»¼½¾¿
|
||||
ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏ
|
||||
ÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞß
|
||||
àáâãäåæçèéêëìíîï
|
||||
ðñòóôõö÷øùúûüýþÿ
|
||||
`.replace(/[ \n]/g,"")
|
||||
}
|
||||
};
|
||||
/* When it's not in the codepage, try and use
|
||||
these conversions */
|
||||
const charFallbacks = {
|
||||
"č":"c",
|
||||
"ř":"r",
|
||||
"ő":"o",
|
||||
"ě":"e"
|
||||
};
|
||||
|
||||
/*
|
||||
timePattern / datePattern:
|
||||
|
||||
|
@ -56,7 +84,7 @@ var locales = {
|
|||
lang: "de_DE",
|
||||
decimal_point: ",",
|
||||
thousands_sep: ".",
|
||||
currency_symbol: "\x80",
|
||||
currency_symbol: "€",
|
||||
int_curr_symbol: "EUR",
|
||||
speed: "kmh",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
@ -92,7 +120,7 @@ var locales = {
|
|||
lang: "en_JP",
|
||||
decimal_point: ".",
|
||||
thousands_sep: ",",
|
||||
currency_symbol: "¥",
|
||||
currency_symbol: "¥",
|
||||
int_curr_symbol: "JPY",
|
||||
speed: "kmh",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
@ -110,7 +138,7 @@ var locales = {
|
|||
lang: "nl_NL",
|
||||
decimal_point: ",",
|
||||
thousands_sep: ".",
|
||||
currency_symbol: "\x80",
|
||||
currency_symbol: "€",
|
||||
int_curr_symbol: "EUR",
|
||||
speed: "kmh",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
@ -146,7 +174,7 @@ var locales = {
|
|||
lang: "fr_FR",
|
||||
decimal_point: ",",
|
||||
thousands_sep: " ",
|
||||
currency_symbol: "\x80",
|
||||
currency_symbol: "€",
|
||||
int_curr_symbol: "EUR",
|
||||
speed: "km/h",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
@ -200,7 +228,7 @@ var locales = {
|
|||
lang: "de_AT",
|
||||
decimal_point: ",",
|
||||
thousands_sep: ".",
|
||||
currency_symbol: "\x80",
|
||||
currency_symbol: "€",
|
||||
int_curr_symbol: "EUR",
|
||||
speed: "kmh",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
@ -217,7 +245,7 @@ var locales = {
|
|||
lang: "en_IL",
|
||||
decimal_point: ",",
|
||||
thousands_sep: ".",
|
||||
currency_symbol: "₪",
|
||||
currency_symbol: "ILS"/*"₪"*/,
|
||||
int_curr_symbol: "ILS",
|
||||
speed: "kmh",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
@ -235,7 +263,7 @@ var locales = {
|
|||
lang: "es_ES",
|
||||
decimal_point: ",",
|
||||
thousands_sep: ".",
|
||||
currency_symbol: "\x80",
|
||||
currency_symbol: "€",
|
||||
int_curr_symbol: "EUR",
|
||||
speed: "kmh",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
@ -253,7 +281,7 @@ var locales = {
|
|||
lang: "fr_BE",
|
||||
decimal_point: ",",
|
||||
thousands_sep: ".",
|
||||
currency_symbol: "\x80",
|
||||
currency_symbol: "€",
|
||||
int_curr_symbol: "EUR",
|
||||
speed: "kmh",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
@ -271,7 +299,7 @@ var locales = {
|
|||
lang: "fi_FI",
|
||||
decimal_point: ",",
|
||||
thousands_sep: ".",
|
||||
currency_symbol: "\x80",
|
||||
currency_symbol: "€",
|
||||
int_curr_symbol: "EUR",
|
||||
speed: "kmh",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
@ -343,7 +371,7 @@ var locales = {
|
|||
lang: "it_IT",
|
||||
decimal_point: ",",
|
||||
thousands_sep: ".",
|
||||
currency_symbol: "\x80",
|
||||
currency_symbol: "€",
|
||||
int_curr_symbol: "EUR",
|
||||
speed: 'kmh',
|
||||
distance: { "0": "m", "1": "km" },
|
||||
|
@ -429,7 +457,7 @@ var locales = {
|
|||
day: "Domingo,Segunda-feira,Terça-feira,Quarta-feira,Quinta-feira,Sexta-feira,Sábado",
|
||||
trans: { yes: "sim", Yes: "Sim", no: "não", No: "Não", ok: "certo", on: "ligado", off: "desligado" }
|
||||
},
|
||||
"cs_CZ": {
|
||||
"cs_CZ": { // THIS NEVER WORKED PROPERLY - many chars are not in the ISO8859-1 codepage and we use charFallbacks
|
||||
lang: "cs_CZ",
|
||||
decimal_point: ",",
|
||||
thousands_sep: " ",
|
||||
|
@ -451,7 +479,7 @@ var locales = {
|
|||
lang: "sl_SI",
|
||||
decimal_point: ",",
|
||||
thousands_sep: ".",
|
||||
currency_symbol: "\x80",
|
||||
currency_symbol: "€",
|
||||
int_curr_symbol: "EUR",
|
||||
speed: "km/h",
|
||||
distance: { 0: "m", 1: "km" },
|
||||
|
|
Loading…
Reference in New Issue