|
|
# -*- coding: utf-8 -*-
|
|
|
|
|
|
# Copyright 2008-2016 Mir Calculate. http://www.calculate-linux.org
|
|
|
#
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
# You may obtain a copy of the License at
|
|
|
#
|
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
|
#
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
# See the License for the specific language governing permissions and
|
|
|
# limitations under the License.
|
|
|
|
|
|
from os import path
|
|
|
import os
|
|
|
from calculate.lib.datavars import ReadonlyVariable
|
|
|
from calculate.lib.utils.common import (getValueFromCmdLine, getXorgConfContent,
|
|
|
getValueFromConfig, CmdlineParams)
|
|
|
from calculate.lib.utils.format import XorgConfig
|
|
|
from collections import OrderedDict
|
|
|
|
|
|
import sys
|
|
|
from calculate.lib.cl_lang import setLocalTranslate, getLazyLocalTranslate
|
|
|
|
|
|
_ = lambda x: x
|
|
|
setLocalTranslate('cl_lib3', sys.modules[__name__])
|
|
|
|
|
|
__ = getLazyLocalTranslate(_)
|
|
|
|
|
|
class Locale(object):
|
|
|
# http://www.localeplanet.com/icu/
|
|
|
langData = OrderedDict([
|
|
|
('be_BY', {
|
|
|
'name': 'Беларуский (Беларусь)',
|
|
|
'layoutname': 'Беларуская',
|
|
|
'locale': 'be_BY.utf8',
|
|
|
'keymap': 'by',
|
|
|
'timezone': 'Europe/Minsk',
|
|
|
'dumpkeys_charset': 'koi8-u',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'us,by',
|
|
|
'language': 'be',
|
|
|
}),
|
|
|
('bg_BG', {
|
|
|
'name': 'Български (България)',
|
|
|
'layoutname': 'Български',
|
|
|
'locale': 'bg_BG.utf8',
|
|
|
'keymap': 'bg_bds-utf8',
|
|
|
'dumpkeys_charset': '',
|
|
|
'timezone': 'Europe/Sofia',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'us,bg',
|
|
|
'language': 'bg',
|
|
|
}),
|
|
|
('bs_BA', {
|
|
|
'name': 'Bosanski (Bosna i Hercegovina)',
|
|
|
'layoutname': 'Bosanski',
|
|
|
'locale': 'bs_BA.utf8',
|
|
|
'keymap': 'slovene',
|
|
|
'timezone': 'Europe/Sarajevo',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'ba',
|
|
|
'language': 'bs',
|
|
|
}),
|
|
|
('cs_CZ', {
|
|
|
'name': 'Čeština (Česká republika)',
|
|
|
'layoutname': 'Čeština',
|
|
|
'locale': 'cs_CZ.utf8',
|
|
|
'keymap': 'cz',
|
|
|
'timezone': 'Europe/Prague',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'cz',
|
|
|
'language': 'cs',
|
|
|
}),
|
|
|
('da_DK', {
|
|
|
'name': 'Dansk (Danmark)',
|
|
|
'layoutname': 'Dansk',
|
|
|
'locale': 'da_DK.utf8',
|
|
|
'keymap': 'dk-latin1',
|
|
|
'timezone': 'Europe/Copenhagen',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'dk',
|
|
|
'language': 'da',
|
|
|
}),
|
|
|
('de_DE', {
|
|
|
'name': 'Deutsch (Deutschland)',
|
|
|
'layoutname': 'Deutsch',
|
|
|
'locale': 'de_DE.utf8',
|
|
|
'keymap': 'de-latin1',
|
|
|
'timezone': 'Europe/Berlin',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'de',
|
|
|
'language': 'de',
|
|
|
}),
|
|
|
('en_AU', {
|
|
|
'name': 'English (Australia)',
|
|
|
'layoutname': 'English',
|
|
|
'locale': 'en_AU.utf8',
|
|
|
'keymap': 'us',
|
|
|
'timezone': 'Australia/Canberra',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'us',
|
|
|
'language': 'en_AU',
|
|
|
}),
|
|
|
('en_GB', {
|
|
|
'name': 'English (United Kingdom)',
|
|
|
'layoutname': 'United Kingdom',
|
|
|
'locale': 'en_GB.utf8',
|
|
|
'keymap': 'uk',
|
|
|
'timezone': 'Europe/London',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'gb',
|
|
|
'language': 'en_GB',
|
|
|
}),
|
|
|
('en_US', {
|
|
|
'name': 'English (United States)',
|
|
|
'layoutname': 'English',
|
|
|
'locale': 'en_US.utf8',
|
|
|
'keymap': 'us',
|
|
|
'timezone': 'America/New_York',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'us',
|
|
|
'language': 'en',
|
|
|
}),
|
|
|
('es_ES', {
|
|
|
'name': 'Español (España)',
|
|
|
'layoutname': 'Español',
|
|
|
'locale': 'es_ES.utf8',
|
|
|
'keymap': 'es euro2',
|
|
|
'timezone': 'Europe/Madrid',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'es',
|
|
|
'language': 'es',
|
|
|
}),
|
|
|
('es_UY', {
|
|
|
'name': 'Español (Uruguay)',
|
|
|
'layoutname': 'Latin American',
|
|
|
'locale': 'es_UY.utf8',
|
|
|
'keymap': 'la-latin1',
|
|
|
'timezone': 'America/Montevideo',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'latam',
|
|
|
'language': 'es_UY',
|
|
|
}),
|
|
|
('es_VE', {
|
|
|
'name': 'Español (Venezuela)',
|
|
|
'layoutname': 'Latin American',
|
|
|
'locale': 'es_VE.utf8',
|
|
|
'keymap': 'la-latin1',
|
|
|
'timezone': 'America/Caracas',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'latam',
|
|
|
'language': 'es_UY',
|
|
|
}),
|
|
|
('et_EE', {
|
|
|
'name': 'Eesti (Eesti)',
|
|
|
'layoutname': 'Eesti',
|
|
|
'locale': 'et_EE.utf8',
|
|
|
'keymap': 'et',
|
|
|
'timezone': 'Europe/Tallinn',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'ee',
|
|
|
'language': 'et',
|
|
|
}),
|
|
|
('fr_BE', {
|
|
|
'name': 'Français (Belgique)',
|
|
|
'layoutname': 'Belgique',
|
|
|
'locale': 'fr_BE.utf8',
|
|
|
'keymap': 'be-latin1',
|
|
|
'timezone': 'Europe/Brussels',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'be',
|
|
|
'language': 'fr',
|
|
|
}),
|
|
|
('fr_CA', {
|
|
|
'name': 'Français (Canada)',
|
|
|
'layoutname': 'French-Canadian',
|
|
|
'locale': 'fr_CA.utf8',
|
|
|
'keymap': 'cf',
|
|
|
'timezone': 'Canada/Pacific',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'ca',
|
|
|
'language': 'fr',
|
|
|
}),
|
|
|
('fr_FR', {
|
|
|
'name': 'Français (France)',
|
|
|
'layoutname': 'Français',
|
|
|
'locale': 'fr_FR.utf8',
|
|
|
'keymap': 'fr-latin9',
|
|
|
'timezone': 'Europe/Paris',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'fr',
|
|
|
'language': 'fr',
|
|
|
}),
|
|
|
('hr_HR', {
|
|
|
'name': 'Hrvatski (Hrvatska)',
|
|
|
'layoutname': 'Hrvatski',
|
|
|
'locale': 'hr_HR.utf8',
|
|
|
'keymap': 'croat',
|
|
|
'timezone': 'Europe/Zagreb',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'hr',
|
|
|
'language': 'hr',
|
|
|
}),
|
|
|
('is_IS', {
|
|
|
'name': 'Íslenska (Ísland)',
|
|
|
'layoutname': 'Íslenska',
|
|
|
'locale': 'is_IS.utf8',
|
|
|
'keymap': 'is-latin1',
|
|
|
'timezone': 'Atlantic/Reykjavik',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'is',
|
|
|
'language': 'is',
|
|
|
}),
|
|
|
('it_IT', {
|
|
|
'name': 'Italiano (Italia)',
|
|
|
'layoutname': 'Italiano',
|
|
|
'locale': 'it_IT.utf8',
|
|
|
'keymap': 'it',
|
|
|
'dumpkeys_charset': '',
|
|
|
'timezone': 'Europe/Rome',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'it',
|
|
|
'language': 'it',
|
|
|
}),
|
|
|
('kk_KZ', {
|
|
|
'name': 'Қазақ тілі (Қазақстан)',
|
|
|
'layoutname': 'Қазақ тілі',
|
|
|
'locale': 'kk_KZ.utf8',
|
|
|
'keymap': 'kaz_gost-unicode',
|
|
|
'timezone': 'Asia/Almaty',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'us,kz',
|
|
|
'language': 'kk',
|
|
|
}),
|
|
|
('lt_LT', {
|
|
|
'name': 'Lietuvių (Lietuva)',
|
|
|
'layoutname': 'Lietuvių',
|
|
|
'locale': 'lt_LT.utf8',
|
|
|
'keymap': 'lt.baltic',
|
|
|
'timezone': 'Europe/Vilnius',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'lt',
|
|
|
'language': 'lt',
|
|
|
}),
|
|
|
('lv_LV', {
|
|
|
'name': 'Latviešu (Latvija)',
|
|
|
'layoutname': 'Latviešu',
|
|
|
'locale': 'lv_LV.utf8',
|
|
|
'keymap': 'lv',
|
|
|
'timezone': 'Europe/Riga',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'lv',
|
|
|
'language': 'lv',
|
|
|
}),
|
|
|
('hu_HU', {
|
|
|
'name': 'Magyar (Magyarország)',
|
|
|
'layoutname': 'Magyar',
|
|
|
'locale': 'hu_HU.utf8',
|
|
|
'keymap': 'hu',
|
|
|
'timezone': 'Europe/Budapest',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'hu',
|
|
|
'language': 'hu',
|
|
|
}),
|
|
|
('nl_BE', {
|
|
|
'name': 'Nederlands (België)',
|
|
|
'layoutname': 'Dutch',
|
|
|
'locale': 'nl_BE.utf8',
|
|
|
'keymap': 'nl',
|
|
|
'timezone': 'Europe/Brussels',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'lat9w-16',
|
|
|
'xkblayout': 'nl',
|
|
|
'language': 'nl_BE',
|
|
|
}),
|
|
|
('nl_NL', {
|
|
|
'name': 'Nederlands (Nederland)',
|
|
|
'layoutname': 'Dutch',
|
|
|
'locale': 'nl_NL.utf8',
|
|
|
'keymap': 'nl',
|
|
|
'timezone': 'Europe/Amsterdam',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'nl',
|
|
|
'language': 'nl_NL',
|
|
|
}),
|
|
|
('nb_NO', {
|
|
|
'name': 'Norsk bokmål (Noreg)',
|
|
|
'layoutname': 'Nynorsk',
|
|
|
'locale': 'nb_NO.utf8',
|
|
|
'keymap': 'no-latin1',
|
|
|
'timezone': 'Europe/Oslo',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'no',
|
|
|
'language': 'nb',
|
|
|
}),
|
|
|
('nn_NO', {
|
|
|
'name': 'Norsk nynorsk (Noreg)',
|
|
|
'layoutname': 'Nynorsk',
|
|
|
'locale': 'nn_NO.utf8',
|
|
|
'keymap': 'no-latin1',
|
|
|
'timezone': 'Europe/Oslo',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'no',
|
|
|
'language': 'nn',
|
|
|
}),
|
|
|
('pl_PL', {
|
|
|
'name': 'Polski (Polska)',
|
|
|
'layoutname': 'Polski',
|
|
|
'locale': 'pl_PL.utf8',
|
|
|
'keymap': 'pl',
|
|
|
'timezone': 'Europe/Warsaw',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'pl',
|
|
|
'language': 'pl',
|
|
|
}),
|
|
|
('pt_BR', {
|
|
|
'name': 'Português (Brasil)',
|
|
|
'layoutname': 'Brasil',
|
|
|
'locale': 'pt_BR.utf8',
|
|
|
'keymap': 'br-abnt2',
|
|
|
'timezone': 'Brazil/East',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'br',
|
|
|
'language': 'pt_BR',
|
|
|
}),
|
|
|
('pt_PT', {
|
|
|
'name': 'Português (Portugal)',
|
|
|
'layoutname': 'Português',
|
|
|
'locale': 'pt_PT.utf8@euro',
|
|
|
'keymap': 'pt-latin9',
|
|
|
'dumpkeys_charset': '',
|
|
|
'timezone': 'Europe/Lisbon',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'pt',
|
|
|
'language': 'pt',
|
|
|
}),
|
|
|
('ro_RO', {
|
|
|
'name': 'Română (România)',
|
|
|
'layoutname': 'Română',
|
|
|
'locale': 'ro_RO.utf8',
|
|
|
'keymap': 'ro_win',
|
|
|
'timezone': 'Europe/Bucharest',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'ro',
|
|
|
'language': 'ro',
|
|
|
}),
|
|
|
('ru_RU', {
|
|
|
'name': 'Русский (Россия)',
|
|
|
'layoutname': 'Русская',
|
|
|
'locale': 'ru_RU.utf8',
|
|
|
'keymap': '-u ruwin_cplk-UTF-8',
|
|
|
'timezone': 'Europe/Moscow',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'us,ru',
|
|
|
'language': 'ru',
|
|
|
}),
|
|
|
('sk_SK', {
|
|
|
'name': 'Slovenčina (Slovenská republika)',
|
|
|
'layoutname': 'Slovenčina',
|
|
|
'locale': 'sk_SK.utf8',
|
|
|
'keymap': 'sk-qwertz',
|
|
|
'dumpkeys_charset': '',
|
|
|
'timezone': 'Europe/Bratislava',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'sk',
|
|
|
'language': 'sk',
|
|
|
}),
|
|
|
('sl_SI', {
|
|
|
'name': 'Slovenščina (Slovenija)',
|
|
|
'layoutname': 'Slovenščina',
|
|
|
'locale': 'sl_SI.utf8',
|
|
|
'keymap': 'slovene',
|
|
|
'timezone': 'Europe/Ljubljana',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'si',
|
|
|
'language': 'sl',
|
|
|
}),
|
|
|
('sq_AL', {
|
|
|
'name': 'Shqip (Shqipëria)',
|
|
|
'layoutname': 'Shqip',
|
|
|
'locale': 'sq_AL.utf8',
|
|
|
'keymap': 'al',
|
|
|
'timezone': 'Europe/Tirane',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'al',
|
|
|
'language': 'sq',
|
|
|
}),
|
|
|
('sr_RS', {
|
|
|
'name': 'Српски (Србија)',
|
|
|
'layoutname': 'Српски',
|
|
|
'locale': 'sr_RS.utf8',
|
|
|
'keymap': 'sr-unicode',
|
|
|
'timezone': 'Europe/Belgrade',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'us,rs',
|
|
|
'language': 'sr',
|
|
|
}),
|
|
|
('fi_FI', {
|
|
|
'name': 'Suomi (Suomi)',
|
|
|
'layoutname': 'Suomi',
|
|
|
'locale': 'fi_FI.utf8',
|
|
|
'keymap': 'fi',
|
|
|
'timezone': 'Europe/Helsinki',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'fi',
|
|
|
'language': 'fi',
|
|
|
}),
|
|
|
('sv_SE', {
|
|
|
'name': 'Svenska (Sverige)',
|
|
|
'layoutname': 'Svenska',
|
|
|
'locale': 'sv_SE.utf8',
|
|
|
'keymap': 'sv-latin1',
|
|
|
'timezone': 'Europe/Stockholm',
|
|
|
'dumpkeys_charset': '',
|
|
|
'consolefont': 'lat0-16',
|
|
|
'xkblayout': 'us,se',
|
|
|
'language': 'sv',
|
|
|
}),
|
|
|
('uk_UA', {
|
|
|
'name': 'Українська (Україна)',
|
|
|
'layoutname': 'Українська',
|
|
|
'locale': 'uk_UA.utf8',
|
|
|
'keymap': 'ua-utf',
|
|
|
'timezone': 'Europe/Kiev',
|
|
|
'dumpkeys_charset': 'koi8-u',
|
|
|
'consolefont': 'ter-v14n',
|
|
|
'xkblayout': 'us,ua',
|
|
|
'language': 'ua',
|
|
|
})
|
|
|
])
|
|
|
|
|
|
default_lang = "en_US"
|
|
|
|
|
|
fields = list(langData[default_lang].keys())
|
|
|
|
|
|
aliases = {
|
|
|
'en_AU': 'en_US',
|
|
|
'es_UY': 'es_VE',
|
|
|
'nl_BE': 'nl_NL',
|
|
|
}
|
|
|
|
|
|
def getLangs(self):
|
|
|
return self.langData.keys()
|
|
|
|
|
|
def getKeyboardLayouts(self):
|
|
|
skip = self.aliases.keys()
|
|
|
return [x for x in self.langData.keys() if x not in skip]
|
|
|
|
|
|
def getLanguages(self):
|
|
|
return map(lambda x: self.langData[x]['language'],
|
|
|
self.langData.keys())
|
|
|
|
|
|
def isLangExists(self, lang):
|
|
|
return lang in self.langData.keys()
|
|
|
|
|
|
def isValueInFieldExists(self, field, value):
|
|
|
return value in map(lambda x: self.langData[x][field],
|
|
|
self.langData.keys())
|
|
|
|
|
|
def getFields(self, field):
|
|
|
return [l[1][field] for l in self.langData.items()]
|
|
|
|
|
|
def getFieldByLang(self, field, lang):
|
|
|
return self.langData.get(lang, self.langData[self.default_lang])[field]
|
|
|
|
|
|
def getLang(self, **kw):
|
|
|
"""
|
|
|
Получить язык по указанному полю.
|
|
|
|
|
|
getLang(keymap="ua-utf")
|
|
|
"""
|
|
|
if not kw:
|
|
|
raise AttributeError("getLang: field missed")
|
|
|
field = next(iter(kw.keys()))
|
|
|
if field not in self.fields:
|
|
|
raise AttributeError("getLang: wrong field")
|
|
|
return self.getLangByField(field, kw[field])
|
|
|
|
|
|
def getKeyboardLayout(self, **kw):
|
|
|
if "lang" in kw:
|
|
|
if kw["lang"] in self.langData:
|
|
|
lang = kw["lang"]
|
|
|
else:
|
|
|
lang = self.default_lang
|
|
|
else:
|
|
|
lang = self.getLang(**kw)
|
|
|
return self.aliases.get(lang, lang)
|
|
|
|
|
|
def __getattr__(self, attrname):
|
|
|
"""
|
|
|
Обработка getKeymap, getXkblayout
|
|
|
"""
|
|
|
if attrname.startswith('get'):
|
|
|
fieldname = attrname[3:].lower()
|
|
|
if fieldname in self.fields:
|
|
|
def wrapper(fieldvalue):
|
|
|
return self.getFieldByLang(fieldname, fieldvalue)
|
|
|
return wrapper
|
|
|
raise AttributeError("'Locale' object has no attribute '%s'" % attrname)
|
|
|
|
|
|
def getLang(self, **kw):
|
|
|
"""
|
|
|
Получить язык по указанному полю.
|
|
|
|
|
|
getLang(keymap="ua-utf")
|
|
|
"""
|
|
|
if not kw:
|
|
|
raise AttributeError("getLang: field missed")
|
|
|
field = next(iter(kw.keys()))
|
|
|
if field not in self.fields:
|
|
|
raise AttributeError("getLang: wrong field")
|
|
|
return self.getLangByField(field, kw[field])
|
|
|
|
|
|
def __getattr__(self, attrname):
|
|
|
"""
|
|
|
Обработка getKeymap, getXkblayout
|
|
|
"""
|
|
|
if attrname.startswith('get'):
|
|
|
fieldname = attrname[3:].lower()
|
|
|
if fieldname in self.fields:
|
|
|
def wrapper(fieldvalue):
|
|
|
return self.getFieldByLang(fieldname, fieldvalue)
|
|
|
return wrapper
|
|
|
raise AttributeError("'Locale' object has no attribute '%s'" % attrname)
|
|
|
|
|
|
def getLangByField(self, field, value):
|
|
|
value = value or ""
|
|
|
if field == 'locale':
|
|
|
value = (value,value.replace('UTF-8','utf8'))
|
|
|
else:
|
|
|
value = (value,)
|
|
|
|
|
|
langs = [lang[0] for lang in self.langData.items()
|
|
|
if lang[1][field] in value]
|
|
|
if not langs:
|
|
|
return self.default_lang
|
|
|
else:
|
|
|
return langs[0]
|
|
|
|
|
|
|
|
|
class VariableOsClockTimezone(ReadonlyVariable):
|
|
|
"""
|
|
|
Current timezone
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
zoneinfodir = "/usr/share/zoneinfo/"
|
|
|
timezonefile = "/etc/timezone"
|
|
|
# try get timezone from kernel calculate param
|
|
|
timezone = getValueFromCmdLine(
|
|
|
CmdlineParams.Calculate, CmdlineParams.Timezone)
|
|
|
if timezone and \
|
|
|
path.exists(path.join(zoneinfodir, timezone)):
|
|
|
return timezone
|
|
|
# get timezone from /etc/timezone
|
|
|
if path.exists(timezonefile):
|
|
|
with open(timezonefile, "r") as f:
|
|
|
return f.read().strip()
|
|
|
return "UTC"
|
|
|
|
|
|
|
|
|
class VariableOsLocaleLocale(ReadonlyVariable, Locale):
|
|
|
"""
|
|
|
Locale (example: ru_RU.utf8)
|
|
|
"""
|
|
|
env_var = "LANG"
|
|
|
|
|
|
def get(self):
|
|
|
# получить значение локали из параметров загрузки ядра
|
|
|
# выбранный язык должен присутствовать в списке поддерживаемых
|
|
|
locale_val = getValueFromCmdLine(
|
|
|
CmdlineParams.Calculate, CmdlineParams.Locale)
|
|
|
if self.isLangExists(locale_val):
|
|
|
cmd_val = self.getLocale(locale_val)
|
|
|
else:
|
|
|
cmd_val = None
|
|
|
|
|
|
# получить значение из файла локали параметров окружения
|
|
|
# выбранный язык должен присутствовать в списке поддерживаемых
|
|
|
locale_file = '/etc/env.d/02locale'
|
|
|
locale_val = getValueFromConfig(locale_file, self.env_var) or ""
|
|
|
locale_val = locale_val.replace('UTF-8','utf8')
|
|
|
if self.isValueInFieldExists('locale', locale_val):
|
|
|
file_val = locale_val
|
|
|
else:
|
|
|
file_val = None
|
|
|
|
|
|
# если параметры локали получены из параетров ядра или окружения
|
|
|
if file_val or cmd_val:
|
|
|
# если система настраивается во время загрузки, то приоритет
|
|
|
# значения параметров загрузки ядра
|
|
|
if self.GetBool('cl_system_boot_set'):
|
|
|
return cmd_val or file_val
|
|
|
else:
|
|
|
return file_val or cmd_val
|
|
|
# если значение окружения не входит с список поддерживаемых
|
|
|
# то используем это значения как есть
|
|
|
if self.env_var in os.environ and os.environ[self.env_var] != "C":
|
|
|
return os.environ[self.env_var]
|
|
|
# во всех остальных случаях вернуть локаль по умолчанию
|
|
|
return self.getLocale("default")
|
|
|
|
|
|
|
|
|
class VariableOsLocaleKeyboardLayout(ReadonlyVariable, Locale):
|
|
|
"""
|
|
|
Раскладка клавиатуры "притянутая" к алиасам ru_RU, en_US и т.д.
|
|
|
"""
|
|
|
def get_xorg_xkblayout(self):
|
|
|
xc = XorgConfig(getXorgConfContent())
|
|
|
for x in (section.option("XkbLayout")
|
|
|
for section in xc.get_sections("InputClass")):
|
|
|
if x:
|
|
|
return x
|
|
|
else:
|
|
|
return ""
|
|
|
|
|
|
def get(self):
|
|
|
# получить значение локали из параметров загрузки ядра
|
|
|
# выбранный язык должен присутствовать в списке поддерживаемых
|
|
|
lang_val = getValueFromCmdLine(
|
|
|
CmdlineParams.Calculate, CmdlineParams.Locale)
|
|
|
if self.isLangExists(lang_val):
|
|
|
cmd_keylayout = self.getKeyboardLayout(lang=lang_val)
|
|
|
else:
|
|
|
cmd_keylayout = None
|
|
|
|
|
|
# получить значение из xorg.conf
|
|
|
xorg_xkb = self.get_xorg_xkblayout()
|
|
|
if self.isValueInFieldExists('xkblayout', xorg_xkb):
|
|
|
xorg_keylayout = self.getKeyboardLayout(xkblayout=xorg_xkb)
|
|
|
else:
|
|
|
xorg_keylayout = None
|
|
|
|
|
|
# получить значение из файла раскладки
|
|
|
# выбранный язык должен присутствовать в списке поддерживаемых
|
|
|
keymap_file = '/etc/conf.d/keymap'
|
|
|
keymap_val = getValueFromConfig(keymap_file, "keymap") or ""
|
|
|
if self.isValueInFieldExists('keymap', keymap_val):
|
|
|
file_keylayout = self.getKeyboardLayout(keymap=keymap_val)
|
|
|
else:
|
|
|
file_keylayout = None
|
|
|
|
|
|
# если параметры локали получены из параетров ядра или окружения
|
|
|
if file_keylayout or cmd_keylayout or xorg_keylayout:
|
|
|
# если система настраивается во время загрузки, то приоритет
|
|
|
# значения параметров загрузки ядра
|
|
|
if self.GetBool('cl_system_boot_set'):
|
|
|
return cmd_keylayout or xorg_keylayout or file_keylayout
|
|
|
else:
|
|
|
return xorg_keylayout or file_keylayout or cmd_keylayout
|
|
|
# во всех остальных случаях вернуть локаль по умолчанию
|
|
|
return self.getKeyboardLayout(lang=self.Get('os_locale_lang'))
|
|
|
|
|
|
|
|
|
class VariableOsLocaleLang(ReadonlyVariable, Locale):
|
|
|
"""
|
|
|
Language (example: ru_RU)
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
"""lang (example: ru_RU)"""
|
|
|
return self.getLang(locale=self.Get('os_locale_locale'))
|
|
|
|
|
|
|
|
|
class VariableOsLocaleLanguage(ReadonlyVariable, Locale):
|
|
|
"""
|
|
|
Short lang name (example: ru)
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
return self.getLanguage(self.Get('os_locale_lang'))
|
|
|
|
|
|
|
|
|
class VariableOsLocaleXkb(ReadonlyVariable, Locale):
|
|
|
"""
|
|
|
Keyboard layout for X server (example: us,ru)
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
"""xkb layouts (example: en,ru)"""
|
|
|
return self.getXkblayout(self.Get('os_locale_keyboard_layout'))
|
|
|
|
|
|
|
|
|
class VariableOsLocaleXkbname(ReadonlyVariable, Locale):
|
|
|
"""
|
|
|
Keyboard layout name for X server (remove value in hooks)
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
locale_xkb = self.Get("os_locale_xkb")
|
|
|
if locale_xkb:
|
|
|
return locale_xkb.split("(")[0]
|
|
|
return ""
|
|
|
|
|
|
|
|
|
class VariableOsLocaleLatSet(ReadonlyVariable, Locale):
|
|
|
"""
|
|
|
Локаль содержит раскладку совместимую с латиницей
|
|
|
|
|
|
Используется для отображения индикатора переключения языка
|
|
|
"""
|
|
|
|
|
|
def get(self):
|
|
|
"""xkb layouts (example: en,ru)"""
|
|
|
layout = self.Get('os_locale_xkbname').split(',')
|
|
|
if len(layout) == 1:
|
|
|
return self.On
|
|
|
else:
|
|
|
return self.Off
|
|
|
|
|
|
|
|
|
class VariableOsLang(ReadonlyVariable, Locale):
|
|
|
"""
|
|
|
Supported langs
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
return self.getLangs()
|
|
|
|
|
|
def humanReadable(self):
|
|
|
return map(lambda x: self.getName(x), self.Get())
|
|
|
|
|
|
class VariableOsKeyboardLayout(ReadonlyVariable, Locale):
|
|
|
"""
|
|
|
Supported keyboard layouts
|
|
|
"""
|
|
|
type = "list"
|
|
|
|
|
|
def get(self):
|
|
|
return self.getKeyboardLayouts()
|
|
|
|
|
|
def humanReadable(self):
|
|
|
return map(lambda x: self.getLayoutname(x), self.Get())
|