1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-04-14 08:17:13 +03:00

Support for changing language.

Fixes #61.
This commit is contained in:
Jonathan Harris 2016-02-07 18:23:38 +00:00
parent 9f03dbcb94
commit 4945bee161
16 changed files with 322 additions and 107 deletions

View File

@ -25,8 +25,8 @@ if platform == 'win32' and getattr(sys, 'frozen', False):
import tempfile import tempfile
sys.stderr = open(join(tempfile.gettempdir(), '%s.log' % appname), 'wt') sys.stderr = open(join(tempfile.gettempdir(), '%s.log' % appname), 'wt')
import l10n from l10n import Translations
l10n.Translations().install() Translations().install(config.get('language') or None)
import companion import companion
import bpc import bpc
@ -85,9 +85,13 @@ class AppWindow:
frame.grid(sticky=tk.NSEW) frame.grid(sticky=tk.NSEW)
frame.columnconfigure(1, weight=1) frame.columnconfigure(1, weight=1)
tk.Label(frame, text=_('Cmdr')+':').grid(row=1, column=0, sticky=tk.W) # Main window self.cmdr_label = tk.Label(frame)
tk.Label(frame, text=_('System')+':').grid(row=2, column=0, sticky=tk.W) # Main window self.system_label = tk.Label(frame)
tk.Label(frame, text=_('Station')+':').grid(row=3, column=0, sticky=tk.W) # Main window self.station_label = tk.Label(frame)
self.cmdr_label.grid(row=1, column=0, sticky=tk.W)
self.system_label.grid(row=2, column=0, sticky=tk.W)
self.station_label.grid(row=3, column=0, sticky=tk.W)
self.cmdr = tk.Label(frame, anchor=tk.W) self.cmdr = tk.Label(frame, anchor=tk.W)
self.system = HyperlinkLabel(frame, compound=tk.RIGHT, url = self.system_url, popup_copy = True) self.system = HyperlinkLabel(frame, compound=tk.RIGHT, url = self.system_url, popup_copy = True)
@ -103,8 +107,9 @@ class AppWindow:
appitem.grid(columnspan=2, sticky=tk.W) appitem.grid(columnspan=2, sticky=tk.W)
self.button = ttk.Button(frame, text=_('Update'), width=28, command=self.getandsend, default=tk.ACTIVE, state=tk.DISABLED) # Update button in main window self.button = ttk.Button(frame, text=_('Update'), width=28, command=self.getandsend, default=tk.ACTIVE, state=tk.DISABLED) # Update button in main window
self.theme_button = tk.Label(frame, text=_('Update'), width = platform == 'darwin' and 32 or 28, state=tk.DISABLED) # Update button in main window self.theme_button = tk.Label(frame, width = platform == 'darwin' and 32 or 28, state=tk.DISABLED)
self.status = tk.Label(frame, name='status', anchor=tk.W) self.status = tk.Label(frame, name='status', anchor=tk.W)
row = frame.grid_size()[1] row = frame.grid_size()[1]
self.button.grid(row=row, columnspan=2, sticky=tk.NSEW) self.button.grid(row=row, columnspan=2, sticky=tk.NSEW)
self.theme_button.grid(row=row, columnspan=2, sticky=tk.NSEW) self.theme_button.grid(row=row, columnspan=2, sticky=tk.NSEW)
@ -118,83 +123,86 @@ class AppWindow:
for child in frame.winfo_children(): for child in frame.winfo_children():
child.grid_configure(padx=5, pady=(platform=='win32' and 1 or 3)) child.grid_configure(padx=5, pady=(platform=='win32' and 1 or 3))
menubar = tk.Menu() self.menubar = tk.Menu()
if platform=='darwin': if platform=='darwin':
# Can't handle (de)iconify if topmost is set, so suppress iconify button # Can't handle (de)iconify if topmost is set, so suppress iconify button
# http://wiki.tcl.tk/13428 and p15 of https://developer.apple.com/legacy/library/documentation/Carbon/Conceptual/HandlingWindowsControls/windowscontrols.pdf # http://wiki.tcl.tk/13428 and p15 of https://developer.apple.com/legacy/library/documentation/Carbon/Conceptual/HandlingWindowsControls/windowscontrols.pdf
root.call('tk::unsupported::MacWindowStyle', 'style', root, 'document', 'closeBox horizontalZoom resizable') root.call('tk::unsupported::MacWindowStyle', 'style', root, 'document', 'closeBox horizontalZoom resizable')
# https://www.tcl.tk/man/tcl/TkCmd/menu.htm # https://www.tcl.tk/man/tcl/TkCmd/menu.htm
apple_menu = tk.Menu(menubar, name='apple') self.file_menu = tk.Menu(self.menubar, name='apple')
apple_menu.add_command(label=_("About {APP}").format(APP=applongname), command=lambda:self.w.call('tk::mac::standardAboutPanel')) # App menu entry on OSX self.file_menu.add_command(command=lambda:self.w.call('tk::mac::standardAboutPanel'))
apple_menu.add_command(label=_("Check for Updates..."), command=lambda:self.updater.checkForUpdates()) self.file_menu.add_command(command=lambda:self.updater.checkForUpdates())
menubar.add_cascade(menu=apple_menu) self.menubar.add_cascade(menu=self.file_menu)
self.edit_menu = tk.Menu(menubar, name='edit') self.edit_menu = tk.Menu(self.menubar, name='edit')
self.edit_menu.add_command(label=_('Copy'), accelerator='Command-c', state=tk.DISABLED, command=self.copy) # As in Copy and Paste self.edit_menu.add_command(accelerator='Command-c', state=tk.DISABLED, command=self.copy)
menubar.add_cascade(label=_('Edit'), menu=self.edit_menu) # Menu title self.menubar.add_cascade(menu=self.edit_menu)
self.w.bind('<Command-c>', self.copy) self.w.bind('<Command-c>', self.copy)
self.view_menu = tk.Menu(menubar, name='view') self.view_menu = tk.Menu(self.menubar, name='view')
self.view_menu.add_command(label=_('Status'), state=tk.DISABLED, command=lambda:stats.StatsDialog(self.w, self.session)) # Menu item self.view_menu.add_command(state=tk.DISABLED, command=lambda:stats.StatsDialog(self.w, self.session))
menubar.add_cascade(label=_('View'), menu=self.view_menu) # Menu title on OSX self.menubar.add_cascade(menu=self.view_menu)
window_menu = tk.Menu(menubar, name='window') window_menu = tk.Menu(self.menubar, name='window')
menubar.add_cascade(label=_('Window'), menu=window_menu) # Menu title on OSX self.menubar.add_cascade(menu=window_menu)
self.w['menu'] = menubar self.w['menu'] = self.menubar
# https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm # https://www.tcl.tk/man/tcl/TkCmd/tk_mac.htm
self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0') self.w.call('set', 'tk::mac::useCompatibilityMetrics', '0')
self.w.createcommand('tkAboutDialog', lambda:self.w.call('tk::mac::standardAboutPanel')) self.w.createcommand('tkAboutDialog', lambda:self.w.call('tk::mac::standardAboutPanel'))
self.w.createcommand("::tk::mac::Quit", self.onexit) self.w.createcommand("::tk::mac::Quit", self.onexit)
self.w.createcommand("::tk::mac::ShowPreferences", lambda:prefs.PreferencesDialog(self.w, self.login)) self.w.createcommand("::tk::mac::ShowPreferences", lambda:prefs.PreferencesDialog(self.w, self.postprefs))
self.w.createcommand("::tk::mac::ReopenApplication", self.w.deiconify) # click on app in dock = restore self.w.createcommand("::tk::mac::ReopenApplication", self.w.deiconify) # click on app in dock = restore
self.w.protocol("WM_DELETE_WINDOW", self.w.withdraw) # close button shouldn't quit app self.w.protocol("WM_DELETE_WINDOW", self.w.withdraw) # close button shouldn't quit app
else: else:
file_menu = self.view_menu = tk.Menu(menubar, tearoff=tk.FALSE) self.file_menu = self.view_menu = tk.Menu(self.menubar, tearoff=tk.FALSE)
file_menu.add_command(label=_('Status'), state=tk.DISABLED, command=lambda:stats.StatsDialog(self.w, self.session)) # Menu item self.file_menu.add_command(state=tk.DISABLED, command=lambda:stats.StatsDialog(self.w, self.session))
file_menu.add_command(label=_("Check for Updates..."), command=lambda:self.updater.checkForUpdates()) self.file_menu.add_command(command=lambda:self.updater.checkForUpdates())
file_menu.add_command(label=_("Settings"), command=lambda:prefs.PreferencesDialog(self.w, self.login)) # Item in the File menu on Windows self.file_menu.add_command(command=lambda:prefs.PreferencesDialog(self.w, self.postprefs))
file_menu.add_separator() self.file_menu.add_separator()
file_menu.add_command(label=_("Exit"), command=self.onexit) # Item in the File menu on Windows self.file_menu.add_command(command=self.onexit)
menubar.add_cascade(label=_("File"), menu=file_menu) # Menu title on Windows self.menubar.add_cascade(menu=self.file_menu)
self.edit_menu = tk.Menu(menubar, tearoff=tk.FALSE) self.edit_menu = tk.Menu(self.menubar, tearoff=tk.FALSE)
self.edit_menu.add_command(label=_('Copy'), accelerator='Ctrl+C', state=tk.DISABLED, command=self.copy) # As in Copy and Paste self.edit_menu.add_command(accelerator='Ctrl+C', state=tk.DISABLED, command=self.copy)
menubar.add_cascade(label=_('Edit'), menu=self.edit_menu) # Menu title self.menubar.add_cascade(menu=self.edit_menu)
if platform == 'win32': if platform == 'win32':
# Must be added after at least one "real" menu entry
self.always_ontop = tk.BooleanVar(value = config.getint('always_ontop')) self.always_ontop = tk.BooleanVar(value = config.getint('always_ontop'))
system_menu = tk.Menu(menubar, name='system', tearoff=tk.FALSE) system_menu = tk.Menu(self.menubar, name='system', tearoff=tk.FALSE)
system_menu.add_separator() system_menu.add_separator()
system_menu.add_checkbutton(label=_('Always on top'), variable = self.always_ontop, command=self.ontop_changed) # Appearance setting system_menu.add_checkbutton(label=_('Always on top'), variable = self.always_ontop, command=self.ontop_changed) # Appearance setting
menubar.add_cascade(menu=system_menu) self.menubar.add_cascade(menu=system_menu) # Gets index 0
self.w.bind('<Control-c>', self.copy) self.w.bind('<Control-c>', self.copy)
self.w.protocol("WM_DELETE_WINDOW", self.onexit) self.w.protocol("WM_DELETE_WINDOW", self.onexit)
theme.register(menubar) # menus and children aren't automatically registered theme.register(self.menubar) # menus and children aren't automatically registered
theme.register(file_menu) theme.register(self.file_menu)
theme.register(self.edit_menu) theme.register(self.edit_menu)
# Alternate title bar and menu for dark theme # Alternate title bar and menu for dark theme
theme_menubar = tk.Frame(frame) self.theme_menubar = tk.Frame(frame)
theme_menubar.columnconfigure(2, weight=1) self.theme_menubar.columnconfigure(2, weight=1)
theme_titlebar = tk.Label(theme_menubar, text=applongname, image=self.theme_icon, anchor=tk.W, compound=tk.LEFT) theme_titlebar = tk.Label(self.theme_menubar, text=applongname, image=self.theme_icon, anchor=tk.W, compound=tk.LEFT)
theme_titlebar.grid(columnspan=3, sticky=tk.NSEW) theme_titlebar.grid(columnspan=3, sticky=tk.NSEW)
self.drag_offset = None self.drag_offset = None
theme_titlebar.bind('<Button-1>', self.drag_start) theme_titlebar.bind('<Button-1>', self.drag_start)
theme_titlebar.bind('<B1-Motion>', self.drag_continue) theme_titlebar.bind('<B1-Motion>', self.drag_continue)
theme_titlebar.bind('<ButtonRelease-1>', self.drag_end) theme_titlebar.bind('<ButtonRelease-1>', self.drag_end)
if platform == 'win32': # Can't work out how to deiconify on Linux if platform == 'win32': # Can't work out how to deiconify on Linux
theme_minimize = tk.Label(theme_menubar, image=self.theme_minimize) theme_minimize = tk.Label(self.theme_menubar, image=self.theme_minimize)
theme_minimize.grid(row=0, column=3) theme_minimize.grid(row=0, column=3)
theme.button_bind(theme_minimize, self.oniconify, image=self.theme_minimize) theme.button_bind(theme_minimize, self.oniconify, image=self.theme_minimize)
theme_close = tk.Label(theme_menubar, image=self.theme_close) theme_close = tk.Label(self.theme_menubar, image=self.theme_close)
theme_close.grid(row=0, column=4) theme_close.grid(row=0, column=4)
theme.button_bind(theme_close, self.onexit, image=self.theme_close) theme.button_bind(theme_close, self.onexit, image=self.theme_close)
theme_file_menu = tk.Label(theme_menubar, text=_('File'), anchor=tk.W) # Menu title on Windows self.theme_file_menu = tk.Label(self.theme_menubar, anchor=tk.W)
theme_file_menu.grid(row=1, column=0, padx=5, sticky=tk.W) self.theme_file_menu.grid(row=1, column=0, padx=5, sticky=tk.W)
theme.button_bind(theme_file_menu, lambda e: file_menu.tk_popup(e.widget.winfo_rootx(), e.widget.winfo_rooty() + e.widget.winfo_height())) theme.button_bind(self.theme_file_menu, lambda e: self.file_menu.tk_popup(e.widget.winfo_rootx(), e.widget.winfo_rooty() + e.widget.winfo_height()))
theme_edit_menu = tk.Label(theme_menubar, text=_('Edit'), anchor=tk.W) # Menu title self.theme_edit_menu = tk.Label(self.theme_menubar, anchor=tk.W) # Menu title
theme_edit_menu.grid(row=1, column=1, sticky=tk.W) self.theme_edit_menu.grid(row=1, column=1, sticky=tk.W)
theme.button_bind(theme_edit_menu, lambda e: self.edit_menu.tk_popup(e.widget.winfo_rootx(), e.widget.winfo_rooty() + e.widget.winfo_height())) theme.button_bind(self.theme_edit_menu, lambda e: self.edit_menu.tk_popup(e.widget.winfo_rootx(), e.widget.winfo_rooty() + e.widget.winfo_height()))
theme.register_highlight(theme_titlebar) theme.register_highlight(theme_titlebar)
theme.register(self.theme_minimize) # images aren't automatically registered theme.register(self.theme_minimize) # images aren't automatically registered
theme.register(self.theme_close) theme.register(self.theme_close)
theme.register_alternate((menubar, theme_menubar), {'row':0, 'columnspan':2, 'sticky':tk.NSEW}) theme.register_alternate((self.menubar, self.theme_menubar), {'row':0, 'columnspan':2, 'sticky':tk.NSEW})
self.set_labels()
# update geometry # update geometry
if config.get('geometry'): if config.get('geometry'):
@ -228,18 +236,44 @@ class AppWindow:
# First run # First run
if not config.get('username') or not config.get('password'): if not config.get('username') or not config.get('password'):
prefs.PreferencesDialog(self.w, self.login) prefs.PreferencesDialog(self.w, self.postprefs)
else: else:
self.login() self.login()
# call after credentials have changed # callback after the Preferences dialog is applied
def postprefs(self):
self.set_labels() # in case language has changed
self.login() # in case credentials gave changed
# set main window labels, e.g. after language change
def set_labels(self):
self.cmdr_label['text'] = _('Cmdr') + ':' # Main window
self.system_label['text'] = _('System') + ':' # Main window
self.station_label['text'] = _('Station') + ':' # Main window
self.button['text'] = self.theme_button['text'] = _('Update') # Update button in main window
self.edit_menu.entryconfigure(0, label=_('Copy')) # As in Copy and Paste
self.view_menu.entryconfigure(0, label=_('Status')) # Menu item
self.file_menu.entryconfigure(1, label=_("Check for Updates...")) # Menu item
if platform == 'darwin':
self.file_menu.entryconfigure(0, label=_("About {APP}").format(APP=applongname)) # App menu entry on OSX
self.menubar.entryconfigure(1, label=_('View')) # Menu title on OSX
self.menubar.entryconfigure(2, label=_('Edit')) # Menu title
self.menubar.entryconfigure(3, label=_('Window')) # Menu title on OSX
else:
self.file_menu.entryconfigure(2, label=_("Settings")) # Item in the File menu on Windows
self.file_menu.entryconfigure(4, label=_("Exit")) # Item in the File menu on Windows
self.menubar.entryconfigure(self.menubar.index('end')-2, label=_('File')) # Menu title on Windows
self.menubar.entryconfigure(self.menubar.index('end')-1, label=_('Edit')) # Menu title
self.theme_file_menu['text'] = _('File') # Menu title on Windows
self.theme_edit_menu['text'] = _('Edit') # Menu title
def login(self): def login(self):
self.status['text'] = _('Logging in...') self.status['text'] = _('Logging in...')
self.button['state'] = self.theme_button['state'] = tk.DISABLED self.button['state'] = self.theme_button['state'] = tk.DISABLED
self.w.update_idletasks() self.w.update_idletasks()
try: try:
self.session.login(config.get('username'), config.get('password')) self.session.login(config.get('username'), config.get('password'))
self.view_menu.entryconfigure(_('Status'), state=tk.NORMAL) self.view_menu.entryconfigure(0, state=tk.NORMAL) # Status
self.status['text'] = '' self.status['text'] = ''
except companion.VerificationRequired: except companion.VerificationRequired:
# don't worry about authentication now - prompt on query # don't worry about authentication now - prompt on query
@ -294,7 +328,7 @@ class AppWindow:
self.system['image'] = '' self.system['image'] = ''
self.status['text'] = _('Fetching data...') self.status['text'] = _('Fetching data...')
self.theme_button['state'] = tk.DISABLED self.theme_button['state'] = tk.DISABLED
self.edit_menu.entryconfigure(_('Copy'), state=tk.DISABLED) self.edit_menu.entryconfigure(0, state=tk.DISABLED) # Copy
self.w.update_idletasks() self.w.update_idletasks()
try: try:
@ -320,8 +354,8 @@ class AppWindow:
self.system['text'] = data.get('lastSystem') and data.get('lastSystem').get('name') or '' self.system['text'] = data.get('lastSystem') and data.get('lastSystem').get('name') or ''
self.station['text'] = data.get('commander') and data.get('commander').get('docked') and data.get('lastStarport') and data.get('lastStarport').get('name') or (EDDB.system(self.system['text']) and self.STATION_UNDOCKED or '') self.station['text'] = data.get('commander') and data.get('commander').get('docked') and data.get('lastStarport') and data.get('lastStarport').get('name') or (EDDB.system(self.system['text']) and self.STATION_UNDOCKED or '')
self.status['text'] = '' self.status['text'] = ''
self.edit_menu.entryconfigure(_('Copy'), state=tk.NORMAL) self.edit_menu.entryconfigure(0, state=tk.NORMAL) # Copy
self.view_menu.entryconfigure(_('Status'), state=tk.NORMAL) self.view_menu.entryconfigure(0, state=tk.NORMAL) # Status
if data['lastStarport'].get('commodities'): if data['lastStarport'].get('commodities'):
# Fixup anomalies in the commodity data # Fixup anomalies in the commodity data

10
L10n/cs.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Čeština";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Ověřovací kód byl odeslán na{CR}e-mailovou adresu spojenou s vašim Elite účtem."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Ověřovací kód byl odeslán na{CR}e-mailovou adresu spojenou s vašim Elite účtem.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Změnit..."; "Change..." = "Změnit...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Zkontrolovat aktualizace..."; "Check for Updates..." = "Zkontrolovat aktualizace...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -97,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Dealer"; "Dealer" = "Dealer";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Výchozí"; "Default" = "Výchozí";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -205,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Knight"; "Knight" = "Knight";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Jazyk";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Naposledy aktualizováno {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Naposledy aktualizováno {HH}:{MM}:{SS}";

10
L10n/de.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Deutsch";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Ein Verifizierungscode wurde an die mit{CR}Elite verknüpfte Email Adresse gesendet."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Ein Verifizierungscode wurde an die mit{CR}Elite verknüpfte Email Adresse gesendet.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Ordner..."; "Change..." = "Ordner...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Auf Aktualisierungen überprüfen..."; "Check for Updates..." = "Auf Aktualisierungen überprüfen...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -97,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Kleinhändler"; "Dealer" = "Kleinhändler";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Standard"; "Default" = "Standard";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -205,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Ritter"; "Knight" = "Ritter";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Sprache";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Zuletzt aktualisiert um {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Zuletzt aktualisiert um {HH}:{MM}:{SS}";

View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "English";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "A verification code has now been sent to the{CR}email address associated with your Elite account."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "A verification code has now been sent to the{CR}email address associated with your Elite account.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Change..."; "Change..." = "Change...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Check for Updates..."; "Check for Updates..." = "Check for Updates...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -97,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Dealer"; "Dealer" = "Dealer";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Default"; "Default" = "Default";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -205,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Knight"; "Knight" = "Knight";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Language";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Last updated at {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Last updated at {HH}:{MM}:{SS}";

10
L10n/es.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Español";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Se ha enviado el código de verificación a la{CR}dirección de correo electrónico asociada a tu cuenta de Frontier."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Se ha enviado el código de verificación a la{CR}dirección de correo electrónico asociada a tu cuenta de Frontier.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Cambiar..."; "Change..." = "Cambiar...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Buscar Actualizaciones..."; "Check for Updates..." = "Buscar Actualizaciones...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -97,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Distribuidor"; "Dealer" = "Distribuidor";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Por defecto"; "Default" = "Por defecto";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -205,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Caballero"; "Knight" = "Caballero";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Idioma";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Última actualización: {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Última actualización: {HH}:{MM}:{SS}";

22
L10n/fr.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Français";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Le code de vérification a été envoyé à l'adresse{CR}e-mail associée à votre compte Elite: Dangerous."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Le code de vérification a été envoyé à l'adresse{CR}e-mail associée à votre compte Elite: Dangerous.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Spécifier..."; "Change..." = "Spécifier...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Chercher une mise à jour..."; "Check for Updates..." = "Chercher une mise à jour...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -67,6 +70,9 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Compétent"; "Competent" = "Compétent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connecté à {EDPROXY} sur {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Temps de recharge {SS}s"; "cooldown {SS}s" = "Temps de recharge {SS}s";
@ -94,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Revendeur"; "Dealer" = "Revendeur";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Par défaut"; "Default" = "Par défaut";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -142,6 +148,9 @@
/* [companion.py] */ /* [companion.py] */
"Error: Server is down" = "Erreur : Le serveur est indisponible"; "Error: Server is down" = "Erreur : Le serveur est indisponible";
/* [companion.py] */
"Error: Verification failed" = "Erreur : La vérification a échouée";
/* Item in the File menu on Windows. [EDMarketConnector.py] */ /* Item in the File menu on Windows. [EDMarketConnector.py] */
"Exit" = "Quitter"; "Exit" = "Quitter";
@ -178,6 +187,9 @@
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Hero" = "Hero"; "Hero" = "Hero";
/* Dark theme color setting. [prefs.py] */
"Highlighted text" = "Texte en surbrillance";
/* Tab heading in settings on Windows. [prefs.py] */ /* Tab heading in settings on Windows. [prefs.py] */
"Hotkey" = "Raccourci clavier"; "Hotkey" = "Raccourci clavier";
@ -196,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Chevalier"; "Knight" = "Chevalier";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Langue";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Dernière mise à jour à {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Dernière mise à jour à {HH}:{MM}:{SS}";
@ -250,6 +265,9 @@
/* No hotkey/shortcut currently defined. [prefs.py] */ /* No hotkey/shortcut currently defined. [prefs.py] */
"None" = "Aucun"; "None" = "Aucun";
/* Dark theme color setting. [prefs.py] */
"Normal text" = "Texte normal";
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Novice" = "Novice"; "Novice" = "Novice";

22
L10n/it.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Italiano";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Un codice di verifica è stato inviato alla email{CR}associata al tuo account di Elite Dangerous."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Un codice di verifica è stato inviato alla email{CR}associata al tuo account di Elite Dangerous.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Cambia..."; "Change..." = "Cambia...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Controlla aggiornamenti..."; "Check for Updates..." = "Controlla aggiornamenti...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -67,6 +70,9 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connesso a {EDPROXY} all'indirizzo {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "disponibile tra {SS} secondi"; "cooldown {SS}s" = "disponibile tra {SS} secondi";
@ -94,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Dealer"; "Dealer" = "Dealer";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Predefinito"; "Default" = "Predefinito";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -142,6 +148,9 @@
/* [companion.py] */ /* [companion.py] */
"Error: Server is down" = "Errore: Il Server è offline"; "Error: Server is down" = "Errore: Il Server è offline";
/* [companion.py] */
"Error: Verification failed" = "Errore: fallita Verifica";
/* Item in the File menu on Windows. [EDMarketConnector.py] */ /* Item in the File menu on Windows. [EDMarketConnector.py] */
"Exit" = "Esci"; "Exit" = "Esci";
@ -178,6 +187,9 @@
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Hero" = "Hero"; "Hero" = "Hero";
/* Dark theme color setting. [prefs.py] */
"Highlighted text" = "Testo evidenziato";
/* Tab heading in settings on Windows. [prefs.py] */ /* Tab heading in settings on Windows. [prefs.py] */
"Hotkey" = "Hotkey"; "Hotkey" = "Hotkey";
@ -196,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Knight"; "Knight" = "Knight";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Lingua";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Ultimo aggiornamento alle {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Ultimo aggiornamento alle {HH}:{MM}:{SS}";
@ -250,6 +265,9 @@
/* No hotkey/shortcut currently defined. [prefs.py] */ /* No hotkey/shortcut currently defined. [prefs.py] */
"None" = "Nessuna"; "None" = "Nessuna";
/* Dark theme color setting. [prefs.py] */
"Normal text" = "Testo normale";
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Novice" = "Novice"; "Novice" = "Novice";

22
L10n/lv.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Latviešu";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Apstiprinājuma kods ir nosūtīts uz {CR} e-pasta adresi, kas ir saistīts ar Jūsu Elite profilu."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Apstiprinājuma kods ir nosūtīts uz {CR} e-pasta adresi, kas ir saistīts ar Jūsu Elite profilu.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Mainīt..."; "Change..." = "Mainīt...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Pārbaudīt atjauninājumus..."; "Check for Updates..." = "Pārbaudīt atjauninājumus...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -67,6 +70,9 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Competent"; "Competent" = "Competent";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "Atskaite {SS}"; "cooldown {SS}s" = "Atskaite {SS}";
@ -94,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Dealer"; "Dealer" = "Dealer";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Noklusējuma"; "Default" = "Noklusējuma";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -142,6 +148,9 @@
/* [companion.py] */ /* [companion.py] */
"Error: Server is down" = "Kļūda: Serveris nav aktīvs"; "Error: Server is down" = "Kļūda: Serveris nav aktīvs";
/* [companion.py] */
"Error: Verification failed" = "Error: Verification failed";
/* Item in the File menu on Windows. [EDMarketConnector.py] */ /* Item in the File menu on Windows. [EDMarketConnector.py] */
"Exit" = "Iziet"; "Exit" = "Iziet";
@ -178,6 +187,9 @@
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Hero" = "Varonis"; "Hero" = "Varonis";
/* Dark theme color setting. [prefs.py] */
"Highlighted text" = "Highlighted text";
/* Tab heading in settings on Windows. [prefs.py] */ /* Tab heading in settings on Windows. [prefs.py] */
"Hotkey" = "Ātrais taustiņš"; "Hotkey" = "Ātrais taustiņš";
@ -196,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Bruņinieks"; "Knight" = "Bruņinieks";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Valoda";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Pēdējo reizi atjaunināts {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Pēdējo reizi atjaunināts {HH}:{MM}:{SS}";
@ -250,6 +265,9 @@
/* No hotkey/shortcut currently defined. [prefs.py] */ /* No hotkey/shortcut currently defined. [prefs.py] */
"None" = "Neviens"; "None" = "Neviens";
/* Dark theme color setting. [prefs.py] */
"Normal text" = "Normal text";
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Novice" = "Novice"; "Novice" = "Novice";

16
L10n/nl.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Nederlands";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Een verificatie code is zojuist verstuurd naar het{CR}e-mail adres behorende bij je Elite account"; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Een verificatie code is zojuist verstuurd naar het{CR}e-mail adres behorende bij je Elite account";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Wijzigen..."; "Change..." = "Wijzigen...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Controleren op updates..."; "Check for Updates..." = "Controleren op updates...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -97,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Dealer"; "Dealer" = "Dealer";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Standaard"; "Default" = "Standaard";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -184,6 +187,9 @@
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Hero" = "Hero"; "Hero" = "Hero";
/* Dark theme color setting. [prefs.py] */
"Highlighted text" = "Highlighted text";
/* Tab heading in settings on Windows. [prefs.py] */ /* Tab heading in settings on Windows. [prefs.py] */
"Hotkey" = "Hotkey"; "Hotkey" = "Hotkey";
@ -202,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Knight"; "Knight" = "Knight";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Taal";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Voor het laatst ververst om {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Voor het laatst ververst om {HH}:{MM}:{SS}";
@ -256,6 +265,9 @@
/* No hotkey/shortcut currently defined. [prefs.py] */ /* No hotkey/shortcut currently defined. [prefs.py] */
"None" = "Geen"; "None" = "Geen";
/* Dark theme color setting. [prefs.py] */
"Normal text" = "Normal text";
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Novice" = "Novice"; "Novice" = "Novice";

10
L10n/pl.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Polski";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Kod weryfikacyjny został wysłany na adres{CR}e-mail powiązany z Twoim kontem w Elite."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Kod weryfikacyjny został wysłany na adres{CR}e-mail powiązany z Twoim kontem w Elite.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Zmień..."; "Change..." = "Zmień...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Sprawdź aktualizacje..."; "Check for Updates..." = "Sprawdź aktualizacje...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -97,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Dealer"; "Dealer" = "Dealer";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Domyślne"; "Default" = "Domyślne";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -205,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Knight"; "Knight" = "Knight";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Język";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Ostatnia aktualizacja {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Ostatnia aktualizacja {HH}:{MM}:{SS}";

22
L10n/ru.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Русский";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Проверочный код был выслан на адрес электронной почты,{CR}указанный в вашей учетной записи Elite: Dangerous."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Проверочный код был выслан на адрес электронной почты,{CR}указанный в вашей учетной записи Elite: Dangerous.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Обзор..."; "Change..." = "Обзор...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Поиск обновлений..."; "Check for Updates..." = "Поиск обновлений...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -67,6 +70,9 @@
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Competent" = "Специалист"; "Competent" = "Специалист";
/* Output settings. [prefs.py] */
"Connected to {EDPROXY} at {ADDR}" = "Connected to {EDPROXY} at {ADDR}";
/* Update button in main window. [EDMarketConnector.py] */ /* Update button in main window. [EDMarketConnector.py] */
"cooldown {SS}s" = "пауза {SS} сек"; "cooldown {SS}s" = "пауза {SS} сек";
@ -94,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Агент"; "Dealer" = "Агент";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "По умолчанию"; "Default" = "По умолчанию";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -142,6 +148,9 @@
/* [companion.py] */ /* [companion.py] */
"Error: Server is down" = "Ошибка: сервер не отвечает"; "Error: Server is down" = "Ошибка: сервер не отвечает";
/* [companion.py] */
"Error: Verification failed" = "Error: Verification failed";
/* Item in the File menu on Windows. [EDMarketConnector.py] */ /* Item in the File menu on Windows. [EDMarketConnector.py] */
"Exit" = "Выход"; "Exit" = "Выход";
@ -178,6 +187,9 @@
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Hero" = "Герой"; "Hero" = "Герой";
/* Dark theme color setting. [prefs.py] */
"Highlighted text" = "Highlighted text";
/* Tab heading in settings on Windows. [prefs.py] */ /* Tab heading in settings on Windows. [prefs.py] */
"Hotkey" = "Горячая клавиша"; "Hotkey" = "Горячая клавиша";
@ -196,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Рыцарь"; "Knight" = "Рыцарь";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Язык";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Последнее обновление {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Последнее обновление {HH}:{MM}:{SS}";
@ -250,6 +265,9 @@
/* No hotkey/shortcut currently defined. [prefs.py] */ /* No hotkey/shortcut currently defined. [prefs.py] */
"None" = "Не назначена"; "None" = "Не назначена";
/* Dark theme color setting. [prefs.py] */
"Normal text" = "Normal text";
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Novice" = "Новичок"; "Novice" = "Новичок";

22
L10n/sl.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Slovenščina";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Koda za preverjanje istovetnosti{CR}je bila poslana na e-poštni naslov."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Koda za preverjanje istovetnosti{CR}je bila poslana na e-poštni naslov.";
@ -25,6 +28,9 @@
/* Output setting. [prefs.py] */ /* Output setting. [prefs.py] */
"Automatically make a log entry on entering a system" = "Shrani podatke v dnevnik leta, ko prispeš v sistem"; "Automatically make a log entry on entering a system" = "Shrani podatke v dnevnik leta, ko prispeš v sistem";
/* [prefs.py] */
"Automatically open uncharted systems EDSM pages" = "Automatically open uncharted systems EDSM pages";
/* Cmdr stats. [stats.py] */ /* Cmdr stats. [stats.py] */
"Balance" = "Ravnotežje"; "Balance" = "Ravnotežje";
@ -46,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Spremeni..."; "Change..." = "Spremeni...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Preveri posodobitve..."; "Check for Updates..." = "Preveri posodobitve...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -94,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Dealer"; "Dealer" = "Dealer";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Privzeta"; "Default" = "Privzeta";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -142,6 +148,9 @@
/* [companion.py] */ /* [companion.py] */
"Error: Server is down" = "Napaka: Strežnik ni na voljo"; "Error: Server is down" = "Napaka: Strežnik ni na voljo";
/* [companion.py] */
"Error: Verification failed" = "Error: Verification failed";
/* Item in the File menu on Windows. [EDMarketConnector.py] */ /* Item in the File menu on Windows. [EDMarketConnector.py] */
"Exit" = "Izhod"; "Exit" = "Izhod";
@ -178,6 +187,9 @@
/* CQC rank. [stats.py] */ /* CQC rank. [stats.py] */
"Hero" = "Hero"; "Hero" = "Hero";
/* Dark theme color setting. [prefs.py] */
"Highlighted text" = "Highlighted text";
/* Tab heading in settings on Windows. [prefs.py] */ /* Tab heading in settings on Windows. [prefs.py] */
"Hotkey" = "Bližnjica"; "Hotkey" = "Bližnjica";
@ -196,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Knight"; "Knight" = "Knight";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Jezik";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Zadnja osvežitev podatkov {HH}:{MM}:{SS} "; "Last updated at {HH}:{MM}:{SS}" = "Zadnja osvežitev podatkov {HH}:{MM}:{SS} ";
@ -250,6 +265,9 @@
/* No hotkey/shortcut currently defined. [prefs.py] */ /* No hotkey/shortcut currently defined. [prefs.py] */
"None" = "Brez"; "None" = "Brez";
/* Dark theme color setting. [prefs.py] */
"Normal text" = "Normal text";
/* Combat rank. [stats.py] */ /* Combat rank. [stats.py] */
"Novice" = "Novice"; "Novice" = "Novice";

10
L10n/uk.strings Normal file → Executable file
View File

@ -1,3 +1,6 @@
/* Language name */
"!Language" = "Українська";
/* Use same text as E:D Launcher's verification dialog. [prefs.py] */ /* Use same text as E:D Launcher's verification dialog. [prefs.py] */
"A verification code has now been sent to the{CR}email address associated with your Elite account." = "Код підтвердження був відправлений на адресу {CR}, що пов'язана з Вашим обліковим записом Elite."; "A verification code has now been sent to the{CR}email address associated with your Elite account." = "Код підтвердження був відправлений на адресу {CR}, що пов'язана з Вашим обліковим записом Elite.";
@ -49,7 +52,7 @@
/* Folder selection button on OSX. [prefs.py] */ /* Folder selection button on OSX. [prefs.py] */
"Change..." = "Внесення змін..."; "Change..." = "Внесення змін...";
/* [EDMarketConnector.py] */ /* Menu item. [EDMarketConnector.py] */
"Check for Updates..." = "Перевірка оновлень..."; "Check for Updates..." = "Перевірка оновлень...";
/* Federation rank. [stats.py] */ /* Federation rank. [stats.py] */
@ -97,7 +100,7 @@
/* Trade rank. [stats.py] */ /* Trade rank. [stats.py] */
"Dealer" = "Дилер"; "Dealer" = "Дилер";
/* Appearance theme setting. [prefs.py] */ /* Appearance theme and language setting. [l10n.py] */
"Default" = "Стандарт"; "Default" = "Стандарт";
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
@ -205,6 +208,9 @@
/* Empire rank. [stats.py] */ /* Empire rank. [stats.py] */
"Knight" = "Лицар"; "Knight" = "Лицар";
/* Appearance setting prompt. [prefs.py] */
"Language" = "Мова";
/* [EDMarketConnector.py] */ /* [EDMarketConnector.py] */
"Last updated at {HH}:{MM}:{SS}" = "Останнє оновлення було {HH}:{MM}:{SS}"; "Last updated at {HH}:{MM}:{SS}" = "Останнє оновлення було {HH}:{MM}:{SS}";

View File

@ -169,12 +169,18 @@ class Session:
pass pass
def login(self, username=None, password=None): def login(self, username=None, password=None):
self.state = Session.STATE_INIT
if (not username or not password): if (not username or not password):
if not self.credentials: if not self.credentials:
raise CredentialsError() raise CredentialsError()
elif self.state == Session.STATE_OK:
return # already logged in
else: else:
self.credentials = { 'email' : username, 'password' : password } credentials = { 'email' : username, 'password' : password }
if self.credentials == credentials and self.state == Session.STATE_OK:
return # already logged in
else:
self.credentials = credentials
self.state = Session.STATE_INIT
try: try:
r = self.session.post(URL_LOGIN, data = self.credentials, timeout=timeout) r = self.session.post(URL_LOGIN, data = self.credentials, timeout=timeout)
except: except:

63
l10n.py
View File

@ -4,6 +4,7 @@
# #
import codecs import codecs
from collections import OrderedDict
import os import os
from os.path import dirname, isfile, join, normpath from os.path import dirname, isfile, join, normpath
import re import re
@ -12,49 +13,64 @@ from sys import platform
import __builtin__ import __builtin__
# Language name
LANGUAGE_ID = '!Language'
class Translations: class Translations:
FALLBACK = 'en' # strings in this code are in English FALLBACK = 'en' # strings in this code are in English
FALLBACK_NAME = 'English'
TRANS_RE = re.compile(r'\s*"([^"]+)"\s*=\s*"([^"]+)"\s*;\s*$')
COMMENT_RE = re.compile(r'\s*/\*.*\*/\s*$')
def __init__(self): def __init__(self):
self.translations = {} self.translations = {}
def install_dummy(self): def install_dummy(self):
# For when translation is not desired or not available # For when translation is not desired or not available
self.translations = {} # not used
__builtin__.__dict__['_'] = lambda x: unicode(x).replace(u'{CR}', u'\n') # Promote strings to Unicode for consistency __builtin__.__dict__['_'] = lambda x: unicode(x).replace(u'{CR}', u'\n') # Promote strings to Unicode for consistency
def install(self): def install(self, lang=None):
available = self.available() available = self.available()
available.add(Translations.FALLBACK) available.add(Translations.FALLBACK)
for preferred in self.preferred(): if not lang:
if preferred in available:
lang = preferred
break
else:
for preferred in self.preferred(): for preferred in self.preferred():
preferred = preferred.split('-',1)[0] # just base language
if preferred in available: if preferred in available:
lang = preferred lang = preferred
break break
else: else:
lang = Translations.FALLBACK for preferred in self.preferred():
preferred = preferred.split('-',1)[0] # just base language
if preferred in available:
lang = preferred
break
if lang not in self.available(): if lang not in self.available():
self.install_dummy() self.install_dummy()
else: else:
regexp = re.compile(r'\s*"([^"]+)"\s*=\s*"([^"]+)"\s*;\s*$') self.translations = self.contents(lang)
comment= re.compile(r'\s*/\*.*\*/\s*$')
with self.file(lang) as h:
for line in h:
if line.strip():
match = regexp.match(line)
if match:
self.translations[match.group(1)] = match.group(2).replace(u'{CR}', u'\n')
elif __debug__ and not comment.match(line):
print 'Bad translation: %s' % line.strip()
__builtin__.__dict__['_'] = self.translate __builtin__.__dict__['_'] = self.translate
def contents(self, lang):
assert lang in self.available()
translations = {}
with self.file(lang) as h:
for line in h:
if line.strip():
match = Translations.TRANS_RE.match(line)
if match:
translations[match.group(1)] = match.group(2).replace(u'{CR}', u'\n')
elif __debug__ and not Translations.COMMENT_RE.match(line):
print 'Bad translation: %s' % line.strip()
if translations.get(LANGUAGE_ID, LANGUAGE_ID) == LANGUAGE_ID:
translations[LANGUAGE_ID] = unicode(lang) # Replace language name with code if missing
return translations
if __debug__: if __debug__:
def translate(self, x): def translate(self, x):
if not self.translations.get(x): if not self.translations.get(x):
@ -75,6 +91,16 @@ class Translations:
available = set([x[:-len('.strings')] for x in os.listdir(path) if x.endswith('.strings')]) available = set([x[:-len('.strings')] for x in os.listdir(path) if x.endswith('.strings')])
return available return available
# Available language names by code
def available_names(self):
names = OrderedDict([
(None, _('Default')), # Appearance theme and language setting
])
names.update(sorted([(lang, self.contents(lang).get(LANGUAGE_ID, lang)) for lang in self.available()] +
[(Translations.FALLBACK, Translations.FALLBACK_NAME)],
key=lambda x: x[1])) # Sort by name
return names
# Returns list of preferred language codes in lowercase RFC4646 format. # Returns list of preferred language codes in lowercase RFC4646 format.
# Typically "lang[-script][-region]" where lang is a 2 alpha ISO 639-1 or 3 alpha ISO 639-2 code, # Typically "lang[-script][-region]" where lang is a 2 alpha ISO 639-1 or 3 alpha ISO 639-2 code,
# script is a 4 alpha ISO 15924 code and region is a 2 alpha ISO 3166 code # script is a 4 alpha ISO 15924 code and region is a 2 alpha ISO 3166 code
@ -149,6 +175,7 @@ if __name__ == "__main__":
seen[match.group(2)] = (match.group(4) and (match.group(4)[1:].strip()) + '. ' or '') + '[%s]' % f seen[match.group(2)] = (match.group(4) and (match.group(4)[1:].strip()) + '. ' or '') + '[%s]' % f
if seen: if seen:
template = codecs.open('L10n/en.template', 'w', 'utf-8') template = codecs.open('L10n/en.template', 'w', 'utf-8')
template.write('/* Language name */\n"%s" = "%s";\n\n' % (LANGUAGE_ID, 'English'))
for thing in sorted(seen, key=unicode.lower): for thing in sorted(seen, key=unicode.lower):
if seen[thing]: if seen[thing]:
template.write('/* %s */\n' % (seen[thing])) template.write('/* %s */\n' % (seen[thing]))

View File

@ -13,6 +13,7 @@ import myNotebook as nb
from config import applongname, config from config import applongname, config
from edproxy import edproxy from edproxy import edproxy
from hotkey import hotkeymgr from hotkey import hotkeymgr
from l10n import Translations
from monitor import monitor from monitor import monitor
from theme import theme from theme import theme
@ -218,6 +219,8 @@ class PreferencesDialog(tk.Toplevel):
_('Keyboard shortcut') or # Tab heading in settings on OSX _('Keyboard shortcut') or # Tab heading in settings on OSX
_('Hotkey')) # Tab heading in settings on Windows _('Hotkey')) # Tab heading in settings on Windows
self.languages = Translations().available_names()
self.lang = tk.StringVar(value = self.languages.get(config.get('language'), _('Default'))) # Appearance theme and language setting
self.always_ontop = tk.BooleanVar(value = config.getint('always_ontop')) self.always_ontop = tk.BooleanVar(value = config.getint('always_ontop'))
self.theme = tk.IntVar(value = config.getint('theme') and 1 or 0) self.theme = tk.IntVar(value = config.getint('theme') and 1 or 0)
self.theme_colors = [config.get('dark_text'), config.get('dark_highlight')] self.theme_colors = [config.get('dark_text'), config.get('dark_highlight')]
@ -227,21 +230,24 @@ class PreferencesDialog(tk.Toplevel):
] ]
themeframe = nb.Frame(notebook) themeframe = nb.Frame(notebook)
themeframe.columnconfigure(2, weight=1) themeframe.columnconfigure(2, weight=1)
nb.Label(themeframe).grid(sticky=tk.W) # big spacer nb.Label(themeframe, text=_('Language')).grid(row=10, padx=PADX, sticky=tk.W) # Appearance setting prompt
self.ontop_button = nb.Checkbutton(themeframe, text=_('Always on top'), variable=self.always_ontop, command=self.themevarchanged) self.lang_button = nb.OptionMenu(themeframe, self.lang, self.lang.get(), *self.languages.values())
self.ontop_button.grid(columnspan=3, padx=BUTTONX, sticky=tk.W) # Appearance setting self.lang_button.grid(row=10, column=1, columnspan=2, padx=PADX, sticky=tk.W)
ttk.Separator(themeframe, orient=tk.HORIZONTAL).grid(columnspan=3, padx=PADX, pady=PADY*8, sticky=tk.EW) ttk.Separator(themeframe, orient=tk.HORIZONTAL).grid(columnspan=3, padx=PADX, pady=PADY*6, sticky=tk.EW)
nb.Label(themeframe, text=_('Theme')).grid(columnspan=3, padx=PADX, sticky=tk.W) # Appearance setting nb.Label(themeframe, text=_('Theme')).grid(columnspan=3, padx=PADX, sticky=tk.W) # Appearance setting
nb.Radiobutton(themeframe, text=_('Default'), variable=self.theme, value=0, command=self.themevarchanged).grid(columnspan=3, padx=BUTTONX, sticky=tk.W) # Appearance theme setting nb.Radiobutton(themeframe, text=_('Default'), variable=self.theme, value=0, command=self.themevarchanged).grid(columnspan=3, padx=BUTTONX, sticky=tk.W) # Appearance theme and language setting
nb.Radiobutton(themeframe, text=_('Dark'), variable=self.theme, value=1, command=self.themevarchanged).grid(columnspan=3, padx=BUTTONX, sticky=tk.W) # Appearance theme setting nb.Radiobutton(themeframe, text=_('Dark'), variable=self.theme, value=1, command=self.themevarchanged).grid(columnspan=3, padx=BUTTONX, sticky=tk.W) # Appearance theme setting
self.theme_label_0 = nb.Label(themeframe, text=self.theme_prompts[0]) self.theme_label_0 = nb.Label(themeframe, text=self.theme_prompts[0])
self.theme_label_0.grid(row=10, padx=PADX, sticky=tk.W) self.theme_label_0.grid(row=20, padx=PADX, sticky=tk.W)
self.theme_button_0 = nb.ColoredButton(themeframe, text=_('Station'), background='black', command=lambda:self.themecolorbrowse(0)) # Main window self.theme_button_0 = nb.ColoredButton(themeframe, text=_('Station'), background='black', command=lambda:self.themecolorbrowse(0)) # Main window
self.theme_button_0.grid(row=10, column=1, padx=PADX, pady=PADY, sticky=tk.NSEW) self.theme_button_0.grid(row=20, column=1, padx=PADX, pady=PADY, sticky=tk.NSEW)
self.theme_label_1 = nb.Label(themeframe, text=self.theme_prompts[1]) self.theme_label_1 = nb.Label(themeframe, text=self.theme_prompts[1])
self.theme_label_1.grid(row=11, padx=PADX, sticky=tk.W) self.theme_label_1.grid(row=21, padx=PADX, sticky=tk.W)
self.theme_button_1 = nb.ColoredButton(themeframe, text=' Hutton Orbital ', background='black', command=lambda:self.themecolorbrowse(1)) # Do not translate self.theme_button_1 = nb.ColoredButton(themeframe, text=' Hutton Orbital ', background='black', command=lambda:self.themecolorbrowse(1)) # Do not translate
self.theme_button_1.grid(row=11, column=1, padx=PADX, pady=PADY, sticky=tk.NSEW) self.theme_button_1.grid(row=21, column=1, padx=PADX, pady=PADY, sticky=tk.NSEW)
ttk.Separator(themeframe, orient=tk.HORIZONTAL).grid(columnspan=3, padx=PADX, pady=PADY*6, sticky=tk.EW)
self.ontop_button = nb.Checkbutton(themeframe, text=_('Always on top'), variable=self.always_ontop, command=self.themevarchanged)
self.ontop_button.grid(columnspan=3, padx=BUTTONX, sticky=tk.W) # Appearance setting
notebook.add(themeframe, text=_('Appearance')) # Tab heading in settings notebook.add(themeframe, text=_('Appearance')) # Tab heading in settings
@ -445,6 +451,10 @@ class PreferencesDialog(tk.Toplevel):
config.set('hotkey_always', int(not self.hotkey_only.get())) config.set('hotkey_always', int(not self.hotkey_only.get()))
config.set('hotkey_mute', int(not self.hotkey_play.get())) config.set('hotkey_mute', int(not self.hotkey_play.get()))
lang_codes = { v: k for k, v in self.languages.iteritems() } # Codes by name
config.set('language', lang_codes.get(self.lang.get()) or '')
Translations().install(config.get('language') or None)
config.set('always_ontop', self.always_ontop.get()) config.set('always_ontop', self.always_ontop.get())
config.set('theme', self.theme.get()) config.set('theme', self.theme.get())
config.set('dark_text', self.theme_colors[0]) config.set('dark_text', self.theme_colors[0])
@ -454,7 +464,7 @@ class PreferencesDialog(tk.Toplevel):
config.set('anonymous', self.out_anon.get()) config.set('anonymous', self.out_anon.get())
self._destroy() self._destroy()
if credentials != (config.get('username'), config.get('password')) and self.callback: if self.callback:
self.callback() self.callback()
def _destroy(self): def _destroy(self):