diff --git a/app/common/setting-definitions.js b/app/common/setting-definitions.js
index 5ae69044..f63a7c08 100755
--- a/app/common/setting-definitions.js
+++ b/app/common/setting-definitions.js
@@ -132,6 +132,20 @@ _VAL[_NAM.CFGS_THEME_NAME] = (v)=>{
return (( v === 'default-dark' || v === 'default' ) ? v : undefined);
};
+// language options
+_NAM.CFGS_LANG_NAME = 'language';
+_DEF[_NAM.CFGS_LANG_NAME] = 'fr';
+_VAL[_NAM.CFGS_LANG_NAME] = (v)=>{
+ return v;
+};
+_NAM.CFGS_LANG_LOCALE = 'lang-locale';
+_DEF[_NAM.CFGS_LANG_LOCALE] = '';
+_VAL[_NAM.CFGS_LANG_LOCALE] = (v)=>{
+ return v;
+};
+// END language
+
+
_NAM.CFGS_SCROLLBAR_COLOR = 'skinny-scrollbar-color';
_DEF[_NAM.CFGS_SCROLLBAR_COLOR] = '';
_VAL[_NAM.CFGS_SCROLLBAR_COLOR] = (v)=>{
diff --git a/app/settings/__custom.css b/app/settings/__custom.css
index 0f9fc9bf..e77faa41 100755
--- a/app/settings/__custom.css
+++ b/app/settings/__custom.css
@@ -25,4 +25,20 @@ span.plain {
text-decoration: none;
}
+#user_locale {
+ display: none;
+ resize: vertical;
+}
+
+#user_locale_btn {
+ display: none;
+ margin-left: 0.5em;
+}
+.floatLeft {
+ float: left;
+}
+.show {
+ display: initial;
+}
+
/* vi: set ts=4 sts=4 sw=4 et ai: */
diff --git a/app/settings/manifest.js b/app/settings/manifest.js
index eb0a580c..3f007742 100755
--- a/app/settings/manifest.js
+++ b/app/settings/manifest.js
@@ -20,7 +20,10 @@ function issue(nums, noparens) {
function brplain(text){return `
${text}`;}
-function future_i18n(x) { return x; }
+function future_i18n(x,n) {
+ var r = n && _T.apply(null, [].slice.call(arguments,1) );
+ return r || x;
+}
let ham = icon('fa fa-bars');
let gt = icon('fa fa-lg fa-caret-right');
@@ -28,97 +31,97 @@ var editImg = icon('fff-pencil tf-action-button');
var delImg = icon('fff-cross tf-action-button');
var saveImg = icon('fff-picture-delete tf-action-button');
let settings = `${ham} ${gt} Settings ${gt}`;
-let refresh_message = " (refresh the TabFern window after you change this to make the change take effect)";
+let refresh_message = future_i18n(" (refresh the TabFern window after you change this to make the change take effect)", 's_refresh_msg');
// Settings {{{2
let setting_definitions = ([
// Welcome page
{
- "tab": future_i18n("Welcome / Help"),
- "group": future_i18n("Introduction"),
+ "tab": future_i18n("Welcome / Help", 's_welcome'),
+ "group": future_i18n("Introduction", 's_intro'),
"name": "welcome-intro",
"type": "description",
- "text": "
Welcome to TabFern! Each Chrome window you have open "+ + "text": future_i18n("
Welcome to TabFern! Each Chrome window you have open "+ "or saved is represented in the TabFern window. "+ "Right-click on those representations or hover " + "the mouse over them for options. Click the " + ham + ' menu for more options.
' + 'The tabs at the left have settings and, at the bottom'+ ' of the list, information about recent feature additions'+ - ' or changes.
' + ' or changes.', 's_intro_txt', ham) }, { - "tab": future_i18n("Welcome / Help"), - "group": future_i18n("Incognito mode"), + "tab": future_i18n("Welcome / Help", 's_welcome'), + "group": future_i18n("Incognito mode", 's_inco'), "type": "description", - "text": + "text": future_i18n( `TabFern cannot see Incognito windows or tabs, and is not yet tested in Incognito mode. If you would like Incognito support in TabFern, please vote at ${issue(125,true)}. -`, +`, 's_inco_txt', issue(125,true) ), }, { - "tab": future_i18n("Welcome / Help"), - "group": future_i18n("Import/Export"), + "tab": future_i18n("Welcome / Help", 's_welcome'), + "group": future_i18n("Import/Export", 's_import'), "name": "export-settings", "id": "export-settings", "type": "button", - "text": "Save settings to a file" + "text": future_i18n("Save settings to a file", 's_save') }, { - "tab": future_i18n("Welcome / Help"), - "group": future_i18n("Import/Export"), + "tab": future_i18n("Welcome / Help", 's_welcome'), + "group": future_i18n("Import/Export", 's_import'), "name": "import-settings", "id": "import-settings", "type": "button", - "text": "Load settings from a file" + "text": future_i18n("Load settings from a file", 's_load') }, { - "tab": future_i18n("Welcome / Help"), - "group": future_i18n("Legal"), + "tab": future_i18n("Welcome / Help", 's_welcome'), + "group": future_i18n("Legal", 's_legal'), "name": "legal", "type": "description", - "text": "The TabFern name, logo, and icons are trademarks of Chris White." + "text": future_i18n("The TabFern name, logo, and icons are trademarks of Chris White.", 's_legal_txt') }, // Behaviour. Yeah, there's a "u" in there! { - "tab": future_i18n("Behaviour"), - "group": future_i18n("When Chrome starts..."), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("When Chrome starts...", 's_chr_st'), "name": S.POPUP_ON_STARTUP, "type": "checkbox", - "label": future_i18n("Open the TabFern window automatically"), + "label": future_i18n("Open the TabFern window automatically", 's_auto_openTF'), }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("When Chrome starts..."), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("When Chrome starts...", 's_chr_st'), "type": "description", - "text": future_i18n("You can open the TabFern window any time by clicking the fern icon next to the address bar."), + "text": future_i18n("You can open the TabFern window any time by clicking the fern icon next to the address bar.", 's_openTF_txt'), }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("On startup or refresh..."), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("On startup or refresh...", 's_startup'), "name": S.COLLAPSE_ON_STARTUP, "type": "checkbox", - "label": future_i18n("Collapse all the saved trees"), + "label": future_i18n("Collapse all the saved trees", 's_collapse'), //"text": future_i18n("x-characters") }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("On startup or refresh..."), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("On startup or refresh...", 's_startup'), "name": S.OPEN_TOP_ON_STARTUP, "type": "checkbox", - "label": future_i18n("Sort open windows to the top") + "label": future_i18n("Sort open windows to the top", 's_sort_open') //"text": future_i18n("x-characters") }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("When I..."), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("When I...", 's_when'), "name": S.COLLAPSE_ON_WIN_CLOSE, "type": "checkbox", - "label": future_i18n("Close an open window, collapse its tree"), + "label": future_i18n("Close an open window, collapse its tree", 's_close_open'), //"text": future_i18n("x-characters") }, // { @@ -130,112 +133,145 @@ vote at ${issue(125,true)}. // //"text": future_i18n("x-characters") // }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("When I..."), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("When I...", 's_when'), "name": S.RESTORE_ON_LAST_DELETED, "type": "checkbox", - "label": future_i18n("Restore the last-deleted window, reopen its tabs"), + "label": future_i18n("Restore the last-deleted window, reopen its tabs", 's_restore_del'), }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("When I..."), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("When I...", 's_when'), "name": S.JUMP_WITH_SORT_OPEN_TOP, "type": "checkbox", - "label": future_i18n('Sort open windows to the top, scroll to the top of the list'), + "label": future_i18n('Sort open windows to the top, scroll to the top of the list', 's_sort_scroll'), }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("When I..."), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("When I...", 's_when'), "name": S.NEW_WINS_AT_TOP, "type": "checkbox", - "label": future_i18n('Open a new window, move it to the top of the list'), + "label": future_i18n('Open a new window, move it to the top of the list', 's_new_top'), }, { // some extra descriptive text for S.NEW_WINS_AT_TOP - "tab": future_i18n("Behaviour"), - "group": future_i18n("When I..."), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("When I...", 's_when'), "type": "description", - "text": `This has the practical side-effect that all open + "text": future_i18n( + `This has the practical side-effect that all open windows will be sorted to the top when you open the TabFern window, even if you didn't check the "Sort - open windows" box above.` + open windows" box above.`, 's_new_top_txt') }, { - 'tab': future_i18n('Behaviour'), - 'group': future_i18n('Partly-open windows'), + 'tab': future_i18n('Behaviour', 's_behaviour'), + 'group': future_i18n('Partly-open windows', 's_partly'), 'name': S.S_OPEN_REST_ON_CLICK, 'type': 'radioButtons', - 'label': `When only some of the tabs in a window are open, + 'label': future_i18n( + `When only some of the tabs in a window are open, what should happen when you click the - name of the window?`, + name of the window?`, 's_partly_txt'), 'options': [ - {value: S.OROC_DO, text: 'Open all the remaining closed tabs'}, - {value: S.OROC_DO_NOT, text: 'Just bring the window to the front' + - ' (you can open the remaining tabs from the right-click menu)'}, + {value: S.OROC_DO, text: future_i18n('Open all the remaining closed tabs', 's_partly_openAllRem')}, + {value: S.OROC_DO_NOT, text: future_i18n('Just bring the window to the front' + + ' (you can open the remaining tabs from the right-click menu)', 's_partly_toFront')}, ], }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("Deleting windows"), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("Deleting windows", 's_del_win'), "name": S.CONFIRM_DEL_OF_SAVED, "type": "checkbox", - "label": future_i18n('Prompt for confirmation before deleting saved windows'), + "label": future_i18n('Prompt for confirmation before deleting saved windows', 's_del_SWin'), }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("Deleting windows"), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("Deleting windows", 's_del_win'), "name": S.CONFIRM_DEL_OF_UNSAVED, "type": "checkbox", - "label": future_i18n('Prompt for confirmation before deleting unsaved windows'), + "label": future_i18n('Prompt for confirmation before deleting unsaved windows', 's_del_UnsWin'), }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("Deleting tabs"), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("Deleting tabs", 's_del_tab'), "name": S.CONFIRM_DEL_OF_SAVED_TABS, "type": "checkbox", - "label": future_i18n('Prompt for confirmation before deleting tabs in saved windows'), + "label": future_i18n('Prompt for confirmation before deleting tabs in saved windows', 's_del_STab'), }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("Deleting tabs"), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("Deleting tabs", 's_del_tab'), "name": S.CONFIRM_DEL_OF_UNSAVED_TABS, "type": "checkbox", - "label": future_i18n('Prompt for confirmation before deleting tabs in unsaved windows'), + "label": future_i18n('Prompt for confirmation before deleting tabs in unsaved windows', 's_del_UnsTab'), }, { - "tab": future_i18n("Behaviour"), - "group": future_i18n("Music"), + "tab": future_i18n("Behaviour", 's_behaviour'), + "group": future_i18n("Music", 's_music'), "name": S.CONFIRM_DEL_OF_AUDIBLE_TABS, "type": "checkbox", - "label": future_i18n('Prompt for confirmation before closing or deleting a tab that is currently playing audio ()'), + "label": future_i18n('Prompt for confirmation before closing or deleting a tab that is currently playing audio ()', 's_music_tab', '()'), }, // Appearance { - "tab": future_i18n("Appearance"), + "tab": future_i18n("Appearance", 's_appear'), "group": '', "type": "description", - "text": future_i18n("Refresh the TabFern window to apply changes to these options. To refresh, click TabFern's title bar and hit F5."), + "text": future_i18n("Refresh the TabFern window to apply changes to these options. To refresh, click TabFern's title bar and hit F5.", 's_appear_txt'), }, { - "tab": future_i18n("Appearance"), - "group": future_i18n("Scrollbars"), + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Language", 's_lang'), + "name": S.S_LANG_NAME, + "type": "popupButton", + "label": future_i18n('Select a language', 's_lang_txt'), + "id": "s_select_lang", + 'options': [ + { value: '', text: future_i18n('Browser default', 's_locDef') }, + { value: '_user_', text: future_i18n('[ User defined ]', 's_locUser') }, + { value: 'en', text: 'English (EN)' }, + { value: 'de', text: 'Deutsch (DE)' }, + { value: 'fr', text: 'Français (FR)' }, + { value: 'ru', text: 'русский (RU)' }, + ], + }, + { + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Language", 's_lang'), + "type": "button", + "text": future_i18n('Edit locale', 's_loc_btn'), + "id": 'user_locale_btn', + }, + { + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Language", 's_lang'), + "name": S.S_LANG_LOCALE, + "type": "textarea", + "style": 'display: none;', + "id": 'user_locale', + }, + { + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Scrollbars", 's_scroll'), "name": S.HIDE_HORIZONTAL_SCROLLBARS, "type": "checkbox", - "label": future_i18n('Hide horizontal scrollbar'), + "label": future_i18n('Hide horizontal scrollbar', 's_hideHscroll'), }, { - "tab": future_i18n("Appearance"), - "group": future_i18n("Scrollbars"), + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Scrollbars", 's_scroll'), "name": S.SKINNY_SCROLLBARS, "type": "checkbox", - "label": future_i18n('Skinny scrollbars'), + "label": future_i18n('Skinny scrollbars', 's_skinnyScroll'), }, { - "tab": future_i18n("Appearance"), - "group": future_i18n("Scrollbars"), + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Scrollbars", 's_scroll'), "id": 'scrollbar-color-picker-label', //"name": '', // Don't save - settings.js handles that "type": "text", @@ -246,37 +282,37 @@ vote at ${issue(125,true)}. // appear properly in search results }, { - "tab": future_i18n("Appearance"), - "group": future_i18n("Tree"), + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Tree", 's_tree'), "name": S.SHOW_TREE_LINES, "type": "checkbox", - "label": future_i18n('Show connecting lines between nodes'), + "label": future_i18n('Show connecting lines between nodes', 's_tree_txt'), }, // Theming options { - "tab": future_i18n("Appearance"), - "group": future_i18n("Theme"), + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Theme", 's_theme'), "name": S.S_THEME_NAME, "type": "popupButton", - "label": future_i18n('Theme'), + "label": future_i18n('Theme', 's_theme'), 'options': [ { value: 'default-dark', text: 'Dark' }, { value: 'default', text: 'Light' }, ], }, { - "tab": future_i18n("Appearance"), - "group": future_i18n("Theme"), + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Theme", 's_theme'), "name": S.S_BACKGROUND, "type": "text", - "label": future_i18n('Background color or image'), + "label": future_i18n('Background color or image', 's_background'), }, { - "tab": future_i18n("Appearance"), - "group": future_i18n("Theme"), + "tab": future_i18n("Appearance", 's_appear'), + "group": future_i18n("Theme", 's_theme'), "type": "description", - "text": + "text": future_i18n( `The background can be specified as a CSS color name, rgb(r,g,b), hsl(h,s,l), or a URL (data, https, chrome-extension, or file). To use images from your local disk (file): @@ -284,35 +320,35 @@ To use images from your local disk (file):Bienvenue sur TabFern! Dans Chrome, chaque fenêtre que vous avez ouverte ou sauvegardée est représentée dans la fenêtre de TabFern. Cliquez avec le bouton droit sur ces éléments ou déplacez la souris par dessus pour accéder aux options. Cliquez le menu $HAM$ pour plus d'options.
Les onglets à gauche contiennent des options et, en bas de la liste, des informations à propos des changements ou ajouts récents.
" + ,"placeholders": { + "ham": { "content": "$1" } + } + } + ,"s_inco": { + "message": "Navigation privée"} + ,"s_inco_txt": { + "message": "TabFern ne peut pas voir les fenêtres et onglets en mode navigation privée, et n'a pas encore été testé en mode navigation privée. Si vous désirez que ce mode soit pris en charge par TabFern, votez ici: $VOTE$" + ,"placeholders": { + "vote": { "content": "$1" } + } + } + ,"s_import": { + "message": "Importer/Exporter"} + ,"s_save": { + "message": "Sauvegarder les réglages dans un fichier"} + ,"s_load": { + "message": "Charger les réglages depuis un fichier"} + ,"s_legal": { + "message": "Mention légale"} + ,"s_legal_txt": { + "message": "Le nom TabFern, le logo, et les icônes sont des marques déposées de Chris White."} + ,"s_behaviour": { + "message": "Comportement"} + ,"s_chr_st": { + "message": "Démarrage de Chrome"} + ,"s_auto_openTF": { + "message": "Ouvrir TabFern automatiquement"} + ,"s_openTF_txt": { + "message": "Vous pouvez ouvrir la fenêtre de TabFern à tout moment en cliquant sur l'icône \"fougère\" à côté de la barre d'adresse."} + ,"s_startup": { + "message": "Au démarrage ou au raffaîchissement..."} + ,"s_collapse": { + "message": "Réduire toutes les arborescences sauvées"} + ,"s_sort_open": { + "message": "Trier les fenêtres ouvertes en haut"} + ,"s_when": { + "message": "Quand je..."} + ,"s_close_open": { + "message": "Ferme une fenêtre, réduire son arborescence"} + ,"s_restore_del": { + "message": "Restaure la dernière fenêtre effacée, rouvrir ses onglets"} + ,"s_sort_scroll": { + "message": "Trie les fenetres ouvertes en haut, faire défiler en faut de la liste"} + ,"s_new_top": { + "message": "Ouvre une nouvelle fenêtre, la déplacer en haut de la liste"} + ,"s_new_top_txt": { + "message": "Ceci a aussi pour effet que toutes fenêtres ouvertes seront triés en haut au moment de l'ouverture de la fenêtre de TabFern. Et ceci même si vous n'avez pas coché l'option \"Trie les fenetres ouvertes\" çi-dessus."} + ,"s_partly": { + "message": "Fenêtres partiellement ouvertes"} + ,"s_partly_txt": { + "message": "Quand seulement certains des onglets sont ouverts, que doit-il se passer quand vous cliquez sur le nom de cette fenêtre ?"} + ,"s_partly_openAllRem": { + "message": "Ouvrir tous les onglets restants"} + ,"s_partly_toFront": { + "message": "Afficher la fenêtre à l'avant-plan (vous pouvez ouvrir les onglets restants depuis le menu clic-droit)"} + ,"s_del_win": { + "message": "Supprimer des fenêtres"} + ,"s_del_SWin": { + "message": "Demander confirmation avant de supprimer une fenêtre sauvegardée"} + ,"s_del_UnsWin": { + "message": "Demander confirmation avant de supprimer une fenêtre non-sauvegardée"} + ,"s_del_tab": { + "message": "Deleting tabs"} + ,"s_del_STab": { + "message": "Demander confirmation avant de supprimer un onglet dans une fenêtre sauvegardée"} + ,"s_del_UnsTab": { + "message": "Demander confirmation avant de supprimer un onglet dans une fenêtre non-sauvegardée"} + ,"s_music": { + "message": "Musique"} + ,"s_music_tab": { + "message": "Demander confirmation avant de fermer ou supprimer un onglet qui diffuse du son $music$" + ,"placeholders": { + "music": { "content": "$1" } + } + } + ,"s_appear": { + "message": "Apparence"} + ,"s_appear_txt": { + "message": "Raffraichir la fenêtre de TabFern pour appliquer la modification des options. Pour raffraichir, cliquer sur la barre de titre de TabFern et appuyer sur F5."} + ,"s_lang": { + "message": "Langue"} + ,"s_lang_txt": { + "message": "Choisissez une langue"} + ,"s_locDef": { + "message": "Défauts du navigateur"} + ,"s_locUser": { + "message": "[ Fournie par l'utilisateur ]"} + ,"s_loc_btn": { + "message": "Editer"} + ,"s_scroll": { + "message": "Barres de défilement"} + ,"s_hideHscroll": { + "message": "Cacher la barre de défilement horizontale"} + ,"s_skinnyScroll": { + "message": "Barres de défilement fines"} + ,"s_skinnyColor": { + "message": "Couleur de la barre de défilement fine (\"X\" pour couleur par défaut)"} + ,"s_tree": { + "message": "Arborescence"} + ,"s_tree_txt": { + "message": "Afficher les lignes de connexion entre les nœuds "} + ,"s_theme": { + "message": "Thème"} + ,"s_background": { + "message": "Couleur ou image de fond"} + ,"s_theme_txt": { + "message": "L'arrière-plan peut être une couleur CSS, rgb(r,g,b), hsl(h,s,l), ou une URL (donnée, https, chrome-extension, ou fichier). Pour utiliser une image de votre disque dur (fichier):