Commit 0a459968 authored by echel0n's avatar echel0n
Browse files

Adding in i18n support for multi-language webui

parent 0b935402
......@@ -239,6 +239,20 @@ module.exports = function (grunt) {
},
all: ['dist/js/core.js']
},
po2json: {
messages: {
options: {
format: 'jed',
singleFile: true
},
files: [{
expand: true,
src: 'sickrage/locale/*/LC_MESSAGES/messages.po',
dest: '',
ext: ''
}]
}
},
changelog: {
release: {
options: {
......@@ -262,6 +276,13 @@ module.exports = function (grunt) {
}
},
exec: {
// Translations
'crowdin_upload': {cmd: 'crowdin-cli-py upload sources'},
'crowdin_download': {cmd: 'crowdin-cli-py download'},
'babel_extract': {cmd: 'python setup.py extract_messages'},
'babel_update': {cmd: 'python setup.py update_catalog'},
'babel_compile': {cmd: 'python setup.py compile_catalog'},
// PyPi Commands
'pypi_publish': {cmd: 'python setup.py sdist bdist_wheel upload clean'},
......@@ -391,8 +412,9 @@ module.exports = function (grunt) {
grunt.file.write(vFile, newVersion);
var git_tasks = [
var tasks = [
'default',
'update_trans', // Update translations
'exec:git_commit:Release v' + newVersion,
'exec:git_flow_start:' + newVersion,
'exec:git_flow_finish:' + newVersion + ':Release v' + newVersion,
......@@ -403,6 +425,25 @@ module.exports = function (grunt) {
'exec:pypi_publish'
];
grunt.task.run(git_tasks);
grunt.task.run(tasks);
});
grunt.registerTask('update_trans', 'Update translations', function() {
grunt.log.writeln('Updating translations...'.magenta);
var tasks = [
'exec:babel_extract',
'exec:babel_update',
'exec:babel_compile',
'po2json'
];
if (process.env.CROWDIN_API_KEY) {
tasks.splice(1, 0, 'exec:crowdin_upload', 'exec:crowdin_download'); // insert items at index 2
} else {
grunt.log.warn('Environment variable `CROWDIN_API_KEY` is not set, not syncing with Crowdin.'.bold);
}
grunt.task.run(tasks);
});
};
\ No newline at end of file
# Changelog
- * 1337903 - 2017-10-13: Release v9.1.36
- * 97ae9f4 - 2017-10-13: Adding in i18n support for multi-language webui
- * 7d2ff8a - 2017-10-13: Release v9.1.36
- * 47dc9a4 - 2017-10-13: Misc code cleanup
- * e127e2a - 2017-10-12: Fixed some typo's
- * a4c60fe - 2017-10-12: Fixed small issue with HDBits
......
project_identifier: sickragetv
api_key_env: CROWDIN_API_KEY
base_url: https://api.crowdin.com
base_path: .
files:
-
source: sickrage/locale/messages.pot
translation: sickrage/locale/%locale_with_underscore%/LC_MESSAGES/messages.po
......@@ -26,6 +26,7 @@
"grunt-sass": "^1.1.0",
"grunt-exec": "^2.0.0",
"grunt-spritesmith": "^6.4.0",
"grunt-po2json": "git+https://github.com/rockykitamura/grunt-po2json.git",
"load-grunt-tasks": "^3.4.1"
}
}
......@@ -2,4 +2,26 @@
description-file = README.txt
[bdist_wheel]
universal = 1
\ No newline at end of file
universal = 1
[extract_messages]
width = 80
charset = utf-8
output-file = sickrage/locale/messages.pot
keywords = _n:1,2
copyright-holder = SiCKRAGE
msgid-bugs-address = [email protected]
add-comments = TRANSLATORS:
[compile_catalog]
directory = sickrage/locale
[init_catalog]
output-dir = sickrage/locale
input-file = sickrage/locale/messages.pot
[update_catalog]
output-dir = sickrage/locale
input-file = sickrage/locale/messages.pot
ignore-obsolete = true
previous = true
\ No newline at end of file
......@@ -3,6 +3,7 @@ import io
import os
import shutil
from babel.messages import frontend as babel
from setuptools import setup, Command
# Get the version number
......@@ -48,11 +49,27 @@ setup(
zip_safe=False,
test_suite='tests',
cmdclass={
'clean': CleanCommand
'clean': CleanCommand,
'compile_catalog': babel.compile_catalog,
'extract_messages': babel.extract_messages,
'init_catalog': babel.init_catalog,
'update_catalog': babel.update_catalog
},
entry_points={
"console_scripts": [
"sickrage=sickrage:main"
]
},
message_extractors={
'sickrage/core/webserver/gui/default': [
('**/views/**.mako', 'mako', {'input_encoding': 'utf-8'})
],
'sickrage': [
('**.py', 'python', None)
],
'dist': [
('**/js/*.min.js', 'ignore', None),
('**/js/*.js', 'javascript', {'input_encoding': 'utf-8'})
],
}
)
......@@ -19,6 +19,7 @@
from __future__ import unicode_literals
import datetime
import gettext
import os
import platform
import re
......@@ -35,6 +36,7 @@ import uuid
import adba
from apscheduler.schedulers.background import BackgroundScheduler
from fake_useragent import UserAgent
from tornado.locale import load_gettext_translations
import sickrage
from sickrage.core.caches.name_cache import srNameCache
......@@ -150,6 +152,10 @@ class Core(object):
self.SYS_ENCODING = get_sys_encoding()
self.LOCALE_DIR = os.path.join(sickrage.PROG_DIR, 'locale')
self.LANGUAGES = [language for language in os.listdir(self.LOCALE_DIR) if '_' in language]
# patch modules with encoding kludge
patch_modules()
......@@ -181,6 +187,16 @@ class Core(object):
# load config
self.srConfig.load()
# set language
if self.srConfig.GUI_LANG:
gettext.translation('messages', self.LOCALE_DIR, languages=[self.srConfig.GUI_LANG],
codeset='UTF-8').install(unicode=1, names=["ngettext"])
else:
gettext.install('messages', self.LOCALE_DIR, unicode=1, codeset='UTF-8', names=["ngettext"])
# load language
load_gettext_translations(self.LOCALE_DIR, 'messages')
# set socket timeout
socket.setdefaulttimeout(self.srConfig.SOCKET_TIMEOUT)
......
......@@ -21,6 +21,7 @@ from __future__ import unicode_literals
import base64
import datetime
import gettext
import os
import os.path
import pickle
......@@ -383,6 +384,7 @@ class srConfig(object):
self.EMAIL_LIST = None
self.GUI_NAME = 'default'
self.GUI_DIR = os.path.join(sickrage.PROG_DIR, 'core', 'webserver', 'gui', self.GUI_NAME)
self.GUI_LANG = ""
self.HOME_LAYOUT = None
self.HISTORY_LAYOUT = None
self.HISTORY_LIMIT = 0
......@@ -513,6 +515,7 @@ class srConfig(object):
'coming_eps_display_paused': False,
'display_show_specials': True,
'gui_name': 'default',
'gui_lang': '',
'history_limit': '100',
'poster_sortdir': 1,
'coming_eps_missed_range': 7,
......@@ -928,6 +931,17 @@ class srConfig(object):
}
}
def change_gui_lang(self, lang):
if lang != self.GUI_LANG:
if lang:
# Selected language
gettext.translation('messages', sickrage.srCore.LOCALE_DIR, languages=[lang], codeset='UTF-8').install(unicode=1, names=["ngettext"])
else:
# System default language
gettext.install('messages', sickrage.srCore.LOCALE_DIR, unicode=1, codeset='UTF-8', names=["ngettext"])
self.GUI_LANG = lang
def change_unrar_tool(self, unrar_tool, unrar_alt_tool):
# Check for failed unrar attempt, and remove it
# Must be done before unrar is ever called or the self-extractor opens and locks startup
......@@ -1564,6 +1578,7 @@ class srConfig(object):
# GUI SETTINGS
self.GUI_NAME = self.check_setting_str('GUI', 'gui_name')
self.GUI_LANG = self.check_setting_str('GUI', 'gui_lang')
self.THEME_NAME = self.check_setting_str('GUI', 'theme_name')
self.FANART_BACKGROUND = self.check_setting_bool('GUI', 'fanart_background')
self.FANART_BACKGROUND_OPACITY = self.check_setting_float('GUI', 'fanart_background_opacity')
......@@ -2034,6 +2049,7 @@ class srConfig(object):
},
'GUI': {
'gui_name': self.GUI_NAME,
'gui_lang': self.GUI_LANG,
'theme_name': self.THEME_NAME,
'home_layout': self.HOME_LAYOUT,
'history_layout': self.HISTORY_LAYOUT,
......
......@@ -4,6 +4,8 @@
import datetime
import locale
from tornado._locale_data import LOCALE_NAMES
import sickrage
from sickrage.core.common import SKIPPED, WANTED, UNAIRED, ARCHIVED, IGNORED, SNATCHED, SNATCHED_PROPER, SNATCHED_BEST, FAILED
from sickrage.core.common import Quality, qualityPresets, statusStrings, qualityPresetStrings, cpu_presets
......@@ -12,6 +14,8 @@
from sickrage.indexers import srIndexerApi
from sickrage.metadata import GenericMetadata
def lang_name(code):
return LOCALE_NAMES.get(code, {}).get("name", "Unknown")
%>
<%block name="tabs">
<li class="active"><a data-toggle="tab" href="#core-tab-pane1">Misc</a></li>
......@@ -331,16 +335,43 @@
</div><!-- /tab-pane1 //-->
<div id="core-tab-pane2" class="tab-pane fade">
<div class="row tab-pane">
<div class="col-lg-3 col-md-4 col-sm-4 col-xs-12 tab-pane-desc">
<h3>User Interface</h3>
<p>Options for visual appearance.</p>
</div>
<fieldset class="col-lg-9 col-md-8 col-sm-8 col-xs-12 tab-pane-list">
<div class="row field-pair">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">Interface Language:</label>
</div>
<div class="col-lg-9 col-md-8 col-sm-7 col-xs-12 component-desc">
<div class="row">
<div class="col-md-12">
<div class="input-group input350">
<div class="input-group-addon">
<span class="fa fa-language"></span>
</div>
<select id="gui_language" name="gui_language" class="form-control">
<option value="" ${('', 'selected="selected"')[sickrage.srCore.srConfig.GUI_LANG == ""]}>System Language</option>
% for lang in sickrage.srCore.LANGUAGES:
<option value="${lang}" ${('', 'selected="selected"')[sickrage.srCore.srConfig.GUI_LANG == lang]}>${lang_name(lang)}</option>
% endfor
</select>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
<label for="gui_language" class="red-text">
for appearance to take effect, save then refresh your browser
</label>
</div>
</div>
</div>
</div>
<div class="row field-pair">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">Display theme:</label>
</div>
......@@ -360,10 +391,9 @@
</select>
</div>
</div>
</div>
<div class="row field-pair">
<div class="row field-pair">
<div class="col-lg-3 col-md-4 col-sm-5 col-xs-12">
<label class="component-title">Show all seasons</label>
</div>
......@@ -784,7 +814,8 @@
<input type="checkbox" name="notify_on_login"
id="notify_on_login" ${('', 'checked')[bool(sickrage.srCore.srConfig.NOTIFY_ON_LOGIN)]}/>
<label for="notify_on_login">
send a message to all enabled notifiers when someone logs into SiCKRAGE from a public IP address
send a message to all enabled notifiers when someone logs into SiCKRAGE from a public IP
address
</label>
</div>
</div>
......
......@@ -724,7 +724,7 @@ class Home(WebHandler):
if connection:
authed, authMsg = SabNZBd.testAuthentication(host, username, password, apikey)
if authed:
return "Success. Connected and authenticated"
return _("Success. Connected and authenticated")
else:
return "Authentication failed. SABnzbd expects '" + accesMsg + "' as authentication method, '" + authMsg + "'"
else:
......@@ -3772,11 +3772,14 @@ class ConfigGeneral(Config):
debug=None, ssl_verify=None, no_restart=None, coming_eps_missed_range=None, filter_row=None,
fuzzy_dating=None, trim_zero=None, date_preset=None, date_preset_na=None, time_preset=None,
indexer_timeout=None, download_url=None, rootDir=None, theme_name=None, default_page=None,
git_reset=None, git_username=None, git_password=None, git_autoissues=None,
git_reset=None, git_username=None, git_password=None, git_autoissues=None, gui_language=None,
display_all_seasons=None, showupdate_stale=None, notify_on_login=None, **kwargs):
results = []
# Language
sickrage.srCore.srConfig.change_gui_lang(gui_language)
# Debug
sickrage.srCore.srConfig.DEBUG = sickrage.srCore.srConfig.checkbox_to_value(debug)
sickrage.srCore.srLogger.set_level()
......
{"messages":{"domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural_forms":"nplurals=2; plural=(n != 1)","lang":"af_ZA"},"Interface Language:":[null,"Interface Taal:"],"System Language":[null,"Stelsel Taal"],"for appearance to take effect, save then refresh your browser":[null,"vir die voorkoms van krag, behalwe dan verfris jou blaaier"],"Symbolic Link Reversed":[null,"Simboliese skakel omgekeerd"],"Please fill out the necessary fields above.":[null,"Vul asseblief die nodige velde hierbo in."],"Success. Connected and authenticated":[null,"Sukses. Gekoppel en geverifieer"]}}}}
\ No newline at end of file
msgid ""
msgstr ""
"Project-Id-Version: sickragetv\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2017-10-13 16:25-0400\n"
"PO-Revision-Date: 2017-10-13 16:26-0400\n"
"Last-Translator: echel0n <[email protected]>\n"
"Language: af_ZA\n"
"Language-Team: Afrikaans\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.5.1\n"
#: sickrage/core/webserver/gui/default/views/config/general.mako:346
msgid "Interface Language:"
msgstr "Interface Taal:"
#: sickrage/core/webserver/gui/default/views/config/general.mako:356
msgid "System Language"
msgstr "Stelsel Taal"
#: sickrage/core/webserver/gui/default/views/config/general.mako:367
msgid "for appearance to take effect, save then refresh your browser"
msgstr "vir die voorkoms van krag, behalwe dan verfris jou blaaier"
#: sickrage/core/webserver/gui/default/views/config/postprocessing.mako:85
msgid "Symbolic Link Reversed"
msgstr "Simboliese skakel omgekeerd"
#: dist/js/core.js:4178
msgid "Please fill out the necessary fields above."
msgstr "Vul asseblief die nodige velde hierbo in."
#: sickrage/core/webserver/views.py:727
msgid "Success. Connected and authenticated"
msgstr "Sukses. Gekoppel en geverifieer"
{"messages":{"domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural_forms":"nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5)","lang":"ar_SA"},"Interface Language:":[null,"لغة الواجهة:"],"System Language":[null,"لغة النظام"],"for appearance to take effect, save then refresh your browser":[null,"ليصبح المظهر ساري المفعول، احفظ ثم قم بتحديث المتصفح"],"Symbolic Link Reversed":[null,"رابط رمزي عكس"],"Please fill out the necessary fields above.":[null,"يرجى ملء الحقول اللازمة أعلاه."],"Success. Connected and authenticated":[null,"نجاح. متصل ومصادقة"]}}}}
\ No newline at end of file
msgid ""
msgstr ""
"Project-Id-Version: sickragetv\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2017-10-13 16:25-0400\n"
"PO-Revision-Date: 2017-10-13 16:26-0400\n"
"Last-Translator: echel0n <[email protected]>\n"
"Language: ar_SA\n"
"Language-Team: Arabic\n"
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : "
"n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.5.1\n"
#: sickrage/core/webserver/gui/default/views/config/general.mako:346
msgid "Interface Language:"
msgstr "لغة الواجهة:"
#: sickrage/core/webserver/gui/default/views/config/general.mako:356
msgid "System Language"
msgstr "لغة النظام"
#: sickrage/core/webserver/gui/default/views/config/general.mako:367
msgid "for appearance to take effect, save then refresh your browser"
msgstr "ليصبح المظهر ساري المفعول، احفظ ثم قم بتحديث المتصفح"
#: sickrage/core/webserver/gui/default/views/config/postprocessing.mako:85
msgid "Symbolic Link Reversed"
msgstr "رابط رمزي عكس"
#: dist/js/core.js:4178
msgid "Please fill out the necessary fields above."
msgstr "يرجى ملء الحقول اللازمة أعلاه."
#: sickrage/core/webserver/views.py:727
msgid "Success. Connected and authenticated"
msgstr "نجاح. متصل ومصادقة"
{"messages":{"domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural_forms":"nplurals=2; plural=(n != 1)","lang":"ca_ES"},"Interface Language:":[null,""],"System Language":[null,""],"for appearance to take effect, save then refresh your browser":[null,""],"Symbolic Link Reversed":[null,""],"Please fill out the necessary fields above.":[null,""],"Success. Connected and authenticated":[null,""]}}}}
\ No newline at end of file
msgid ""
msgstr ""
"Project-Id-Version: sickragetv\n"
"Report-Msgid-Bugs-To: [email protected]\n"
"POT-Creation-Date: 2017-10-13 16:25-0400\n"
"PO-Revision-Date: 2017-10-13 15:07-0400\n"
"Last-Translator: echel0n <[email protected]>\n"
"Language: ca_ES\n"
"Language-Team: Catalan\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.5.1\n"
#: sickrage/core/webserver/gui/default/views/config/general.mako:346
msgid "Interface Language:"
msgstr ""
#: sickrage/core/webserver/gui/default/views/config/general.mako:356
msgid "System Language"
msgstr ""
#: sickrage/core/webserver/gui/default/views/config/general.mako:367
msgid "for appearance to take effect, save then refresh your browser"
msgstr ""
#: sickrage/core/webserver/gui/default/views/config/postprocessing.mako:85
msgid "Symbolic Link Reversed"
msgstr ""
#: dist/js/core.js:4178
msgid "Please fill out the necessary fields above."
msgstr ""
#: sickrage/core/webserver/views.py:727
msgid "Success. Connected and authenticated"
msgstr ""
{"messages":{"domain":"messages","locale_data":{"messages":{"":{"domain":"messages","plural_forms":"nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2","lang":"cs_CZ"},"Interface Language:":[null,"Jazyk rozhraní:"],"System Language":[null,"Systémový jazyk"],"for appearance to take effect, save then refresh your browser":[null,"aby se vzhled projevil, uložte a aktualizujte svůj prohlížeč"],"Symbolic Link Reversed":[null,"Symbolický odkaz obráceně"],"Please fill out the necessary fields above.":[null,"Vyplňte prosím výše uvedená pole."],"Success. Connected and authenticated":[null,"Úspěch. Připojeno a ověřeno"]}}}}
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment