widelands-dev team mailing list archive
-
widelands-dev team
-
Mailing list archive
-
Message #11273
[Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
GunChleoc has proposed merging lp:~widelands-dev/widelands/translation_stats into lp:widelands.
Commit message:
Show translation stats next to the language selection menu and invite translators if a translation is incomplete, with the help of the Translate Toolkit.
- Added a new utils script "update_translation_stats.py" that will write translation statistics to data/i18n/translation_stats.conf.
This script is now called on every translation pull.
- Added translation stats + invitation to translators to Options.
Requested reviews:
Widelands Developers (widelands-dev)
For more details, see:
https://code.launchpad.net/~widelands-dev/widelands/translation_stats/+merge/332029
Some translations have very little work accomplished, so I thought we'd better tell the user so. This also gives us an opportunity to invite translators.
--
Your team Widelands Developers is requested to review the proposed merge of lp:~widelands-dev/widelands/translation_stats into lp:widelands.
=== added file 'data/i18n/translation_stats.conf'
--- data/i18n/translation_stats.conf 1970-01-01 00:00:00 +0000
+++ data/i18n/translation_stats.conf 2017-10-09 19:42:37 +0000
@@ -0,0 +1,239 @@
+[ar]
+translated=3400
+total=41289
+
+[ast]
+translated=471
+total=41289
+
+[bg]
+translated=41289
+total=41289
+
+[br]
+translated=422
+total=41289
+
+[ca]
+translated=41289
+total=41289
+
+[cs]
+translated=40858
+total=41289
+
+[da]
+translated=40774
+total=41289
+
+[de]
+translated=41009
+total=41289
+
+[el]
+translated=493
+total=41289
+
+[en_CA]
+translated=558
+total=41289
+
+[en_GB]
+translated=40774
+total=41289
+
+[en_US]
+translated=7
+total=41289
+
+[eo]
+translated=4455
+total=41289
+
+[es]
+translated=39621
+total=41289
+
+[et]
+translated=628
+total=41289
+
+[eu]
+translated=1359
+total=41289
+
+[fa]
+translated=123
+total=41289
+
+[fi]
+translated=41289
+total=41289
+
+[fr]
+translated=40891
+total=41289
+
+[ga]
+translated=0
+total=41289
+
+[gd]
+translated=41289
+total=41289
+
+[gl]
+translated=10511
+total=41289
+
+[he]
+translated=422
+total=41289
+
+[hi]
+translated=26
+total=41289
+
+[hr]
+translated=3239
+total=41289
+
+[hu]
+translated=33263
+total=41289
+
+[ia]
+translated=126
+total=41289
+
+[id]
+translated=34
+total=41289
+
+[it]
+translated=36675
+total=41289
+
+[ja]
+translated=7025
+total=41289
+
+[jv]
+translated=22
+total=41289
+
+[ka]
+translated=4
+total=41289
+
+[ko]
+translated=209
+total=41289
+
+[krl]
+translated=14
+total=41289
+
+[la]
+translated=4012
+total=41289
+
+[lt]
+translated=202
+total=41289
+
+[mr]
+translated=7
+total=41289
+
+[ms]
+translated=4099
+total=41289
+
+[my]
+translated=30
+total=41289
+
+[nb]
+translated=9192
+total=41289
+
+[nds]
+translated=876
+total=41289
+
+[nl]
+translated=34028
+total=41289
+
+[nn]
+translated=2946
+total=41289
+
+[oc]
+translated=195
+total=41289
+
+[pl]
+translated=41009
+total=41289
+
+[pt]
+translated=28352
+total=41289
+
+[pt_BR]
+translated=14495
+total=41289
+
+[ro]
+translated=1125
+total=41289
+
+[ru]
+translated=41289
+total=41289
+
+[rw]
+translated=49
+total=41289
+
+[si]
+translated=283
+total=41289
+
+[sk]
+translated=39563
+total=41289
+
+[sl]
+translated=1046
+total=41289
+
+[sr]
+translated=177
+total=41289
+
+[sv]
+translated=38623
+total=41289
+
+[tr]
+translated=1942
+total=41289
+
+[uk]
+translated=3621
+total=41289
+
+[vi]
+translated=1199
+total=41289
+
+[zh_CN]
+translated=2245
+total=41289
+
+[zh_TW]
+translated=655
+total=41289
=== modified file 'src/ui_fsmenu/options.cc'
--- src/ui_fsmenu/options.cc 2017-09-11 16:59:41 +0000
+++ src/ui_fsmenu/options.cc 2017-10-09 19:42:37 +0000
@@ -36,6 +36,7 @@
#include "graphic/text/bidi.h"
#include "graphic/text/font_set.h"
#include "graphic/text_constants.h"
+#include "graphic/text_layout.h"
#include "helper.h"
#include "io/filesystem/layered_filesystem.h"
#include "logic/constants.h"
@@ -47,23 +48,6 @@
namespace {
-// Data model for the entries in the language selection list.
-struct LanguageEntry {
- LanguageEntry(const std::string& init_localename,
- const std::string& init_descname,
- const std::string& init_sortname)
- : localename(init_localename), descname(init_descname), sortname(init_sortname) {
- }
-
- bool operator<(const LanguageEntry& other) const {
- return sortname < other.sortname;
- }
-
- std::string localename; // ISO code for the locale
- std::string descname; // Native language name
- std::string sortname; // ASCII Language name used for sorting
-};
-
// Locale identifiers can look like this: ca_ES@xxxxxxxxxxxx-8
// The contents of 'selected_locale' will be changed to match the 'current_locale'
void find_selected_locale(std::string* selected_locale, const std::string& current_locale) {
@@ -120,21 +104,23 @@
// Tabs
tabs_(this, g_gr->images().get("images/ui_basic/but1.png"), UI::TabPanel::Type::kBorder),
- box_interface_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
+ box_interface_(&tabs_, 0, 0, UI::Box::Horizontal, 0, 0, padding_),
+ box_interface_left_(&box_interface_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
box_windows_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
box_sound_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
box_saving_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
box_game_(&tabs_, 0, 0, UI::Box::Vertical, 0, 0, padding_),
// Interface options
- language_dropdown_(&box_interface_,
+ // NOCOM this will only work when bug-536489-pictorial-dropdown has been merged.
+ language_dropdown_(&box_interface_left_,
0,
0,
100, // 100 is arbitrary, will be resized in layout().
100, // 100 is arbitrary, will be resized in layout().
24,
_("Language")),
- resolution_dropdown_(&box_interface_,
+ resolution_dropdown_(&box_interface_left_,
0,
0,
100, // 100 is arbitrary, will be resized in layout().
@@ -142,10 +128,10 @@
24,
_("In-game resolution")),
- fullscreen_(&box_interface_, Vector2i::zero(), _("Fullscreen"), "", 0),
- inputgrab_(&box_interface_, Vector2i::zero(), _("Grab Input"), "", 0),
-
- sb_maxfps_(&box_interface_, 0, 0, 0, 0, opt.maxfps, 0, 99, _("Maximum FPS:")),
+ fullscreen_(&box_interface_left_, Vector2i::zero(), _("Fullscreen"), "", 0),
+ inputgrab_(&box_interface_left_, Vector2i::zero(), _("Grab Input"), "", 0),
+ sb_maxfps_(&box_interface_left_, 0, 0, 0, 0, opt.maxfps, 0, 99, _("Maximum FPS:")),
+ translation_info_(&box_interface_, 0, 0, 100, 100),
// Windows options
snap_win_overlap_only_(
@@ -232,6 +218,7 @@
os_(opt) {
// Set up UI Elements
title_.set_fontsize(UI_FONT_SIZE_BIG);
+ translation_info_.force_new_renderer();
// Buttons
button_box_.add(UI::g_fh1->fontset()->is_rtl() ? &ok_ : &cancel_);
@@ -252,18 +239,14 @@
tabs_.activate(os_.active_tab);
}
- box_interface_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
- box_windows_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
- box_sound_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
- box_saving_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
- box_game_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
-
// Interface
- box_interface_.add(&language_dropdown_);
- box_interface_.add(&resolution_dropdown_);
- box_interface_.add(&fullscreen_);
- box_interface_.add(&inputgrab_);
- box_interface_.add(&sb_maxfps_);
+ box_interface_.add(&box_interface_left_);
+ box_interface_.add(&translation_info_, UI::Box::Resizing::kExpandBoth);
+ box_interface_left_.add(&language_dropdown_);
+ box_interface_left_.add(&resolution_dropdown_);
+ box_interface_left_.add(&fullscreen_);
+ box_interface_left_.add(&inputgrab_);
+ box_interface_left_.add(&sb_maxfps_);
// Windows
box_windows_.add(&snap_win_overlap_only_);
@@ -290,6 +273,8 @@
box_game_.add(&single_watchwin_);
// Bind actions
+ language_dropdown_.selected.connect(
+ boost::bind(&FullscreenMenuOptions::update_language_stats, this, false));
cancel_.sigclicked.connect(boost::bind(&FullscreenMenuOptions::clicked_back, this));
apply_.sigclicked.connect(boost::bind(&FullscreenMenuOptions::clicked_apply, this));
ok_.sigclicked.connect(boost::bind(&FullscreenMenuOptions::clicked_ok, this));
@@ -360,6 +345,7 @@
// Language options
add_languages_to_list(opt.language);
+ update_language_stats(true);
layout();
}
@@ -369,8 +355,7 @@
butw_ = get_w() / 5;
buth_ = get_h() * 9 / 200;
hmargin_ = get_w() * 19 / 200;
- tab_panel_width_ = get_inner_w() - 2 * hmargin_;
- column_width_ = tab_panel_width_ - padding_;
+ int tab_panel_width = get_inner_w() - 2 * hmargin_;
tab_panel_y_ = get_h() * 14 / 100;
// Title
@@ -382,48 +367,53 @@
apply_.set_desired_size(butw_, buth_);
ok_.set_desired_size(butw_, buth_);
button_box_.set_pos(Vector2i(hmargin_ + butw_ / 3, get_inner_h() - hmargin_));
- button_box_.set_size(tab_panel_width_ - 2 * butw_ / 3, buth_);
+ button_box_.set_size(tab_panel_width - 2 * butw_ / 3, buth_);
// Tabs
tabs_.set_pos(Vector2i(hmargin_, tab_panel_y_));
- tabs_.set_size(tab_panel_width_, get_inner_h() - tab_panel_y_ - buth_ - hmargin_);
+ tabs_.set_size(tab_panel_width, get_inner_h() - tab_panel_y_ - buth_ - hmargin_);
+
+ tab_panel_width -= padding_;
+ const int column_width = tab_panel_width / 2;
// Interface
- language_dropdown_.set_desired_size(column_width_ / 2, language_dropdown_.get_h());
+ box_interface_left_.set_desired_size(column_width + padding_, tabs_.get_inner_h());
+ box_interface_.set_size(tabs_.get_inner_w(), tabs_.get_inner_h());
+ language_dropdown_.set_desired_size(column_width, language_dropdown_.get_h());
language_dropdown_.set_height(tabs_.get_h() - language_dropdown_.get_y() - buth_ - 3 * padding_);
- resolution_dropdown_.set_desired_size(column_width_ / 2, resolution_dropdown_.get_h());
+ resolution_dropdown_.set_desired_size(column_width, resolution_dropdown_.get_h());
resolution_dropdown_.set_height(tabs_.get_h() - resolution_dropdown_.get_y() - buth_ -
3 * padding_);
- fullscreen_.set_desired_size(column_width_, fullscreen_.get_h());
- inputgrab_.set_desired_size(column_width_, inputgrab_.get_h());
- sb_maxfps_.set_unit_width(column_width_ / 4);
- sb_maxfps_.set_desired_size(column_width_ / 2, sb_maxfps_.get_h());
+ fullscreen_.set_desired_size(column_width, fullscreen_.get_h());
+ inputgrab_.set_desired_size(column_width, inputgrab_.get_h());
+ sb_maxfps_.set_unit_width(column_width / 2);
+ sb_maxfps_.set_desired_size(column_width, sb_maxfps_.get_h());
// Windows options
- snap_win_overlap_only_.set_desired_size(column_width_, snap_win_overlap_only_.get_h());
- dock_windows_to_edges_.set_desired_size(column_width_, dock_windows_to_edges_.get_h());
- animate_map_panning_.set_desired_size(column_width_, animate_map_panning_.get_h());
+ snap_win_overlap_only_.set_desired_size(tab_panel_width, snap_win_overlap_only_.get_h());
+ dock_windows_to_edges_.set_desired_size(tab_panel_width, dock_windows_to_edges_.get_h());
+ animate_map_panning_.set_desired_size(tab_panel_width, animate_map_panning_.get_h());
sb_dis_panel_.set_unit_width(200);
- sb_dis_panel_.set_desired_size(column_width_, sb_dis_panel_.get_h());
+ sb_dis_panel_.set_desired_size(tab_panel_width, sb_dis_panel_.get_h());
sb_dis_border_.set_unit_width(200);
- sb_dis_border_.set_desired_size(column_width_, sb_dis_border_.get_h());
+ sb_dis_border_.set_desired_size(tab_panel_width, sb_dis_border_.get_h());
// Sound options
- music_.set_desired_size(column_width_, music_.get_h());
- fx_.set_desired_size(column_width_, fx_.get_h());
- message_sound_.set_desired_size(column_width_, message_sound_.get_h());
+ music_.set_desired_size(tab_panel_width, music_.get_h());
+ fx_.set_desired_size(tab_panel_width, fx_.get_h());
+ message_sound_.set_desired_size(tab_panel_width, message_sound_.get_h());
// Saving options
sb_autosave_.set_unit_width(250);
- sb_autosave_.set_desired_size(column_width_, sb_autosave_.get_h());
+ sb_autosave_.set_desired_size(tab_panel_width, sb_autosave_.get_h());
sb_rolling_autosave_.set_unit_width(250);
- sb_rolling_autosave_.set_desired_size(column_width_, sb_rolling_autosave_.get_h());
- zip_.set_desired_size(column_width_, zip_.get_h());
- write_syncstreams_.set_desired_size(column_width_, write_syncstreams_.get_h());
+ sb_rolling_autosave_.set_desired_size(tab_panel_width, sb_rolling_autosave_.get_h());
+ zip_.set_desired_size(tab_panel_width, zip_.get_h());
+ write_syncstreams_.set_desired_size(tab_panel_width, write_syncstreams_.get_h());
// Game options
- transparent_chat_.set_desired_size(column_width_, transparent_chat_.get_h());
+ transparent_chat_.set_desired_size(tab_panel_width, transparent_chat_.get_h());
}
void FullscreenMenuOptions::add_languages_to_list(const std::string& current_locale) {
@@ -432,7 +422,7 @@
language_dropdown_.add(_("Try system language"), "", nullptr, current_locale == "");
language_dropdown_.add("English", "en", nullptr, current_locale == "en");
- // Add translation directories to the list
+ // Add translation directories to the list. We use a vector so we can call std::sort on it.
std::vector<LanguageEntry> entries;
std::string selected_locale;
@@ -460,7 +450,9 @@
std::string name = i18n::make_ligatures(table->get_string("name").c_str());
const std::string sortname = table->get_string("sort_name");
- entries.push_back(LanguageEntry(localename, name, sortname));
+ LanguageEntry* entry = new LanguageEntry(localename, name, sortname);
+ entries.push_back(*entry);
+ language_entries_.insert(std::make_pair(localename, *entry));
if (localename == current_locale) {
selected_locale = current_locale;
@@ -484,6 +476,67 @@
}
}
+/**
+ * Updates the language statistics message according to the currently selected locale.
+ * @param include_system_lang We only want to include the system lang if it matches the Widelands
+ * locale.
+ */
+void FullscreenMenuOptions::update_language_stats(bool include_system_lang) {
+ int percent = 100;
+ std::string message = "";
+ if (language_dropdown_.has_selection()) {
+ std::string locale = language_dropdown_.get_selected();
+ // Empty locale means try system locale
+ if (locale.empty() && include_system_lang) {
+ std::vector<std::string> parts;
+ boost::split(parts, i18n::get_locale(), boost::is_any_of("."));
+ if (language_entries_.count(parts[0]) == 1) {
+ locale = parts[0];
+ } else {
+ boost::split(parts, parts[0], boost::is_any_of("@"));
+ if (language_entries_.count(parts[0]) == 1) {
+ locale = parts[0];
+ } else {
+ boost::split(parts, parts[0], boost::is_any_of("_"));
+ if (language_entries_.count(parts[0]) == 1) {
+ locale = parts[0];
+ }
+ }
+ }
+ }
+
+ // If we have the locale, grab the stats and set the message
+ if (language_entries_.count(locale) == 1) {
+ try {
+ const LanguageEntry& entry = language_entries_[locale];
+ Profile prof("i18n/translation_stats.conf");
+ Section& s = prof.get_safe_section(locale);
+ percent = floor(100.f * s.get_int("translated") / s.get_int("total"));
+ if (percent == 100) {
+ message = (boost::format(_("The translation into %s is complete.")) %
+ entry.descname)
+ .str();
+ } else {
+ message = (boost::format(_("The translation into %s is %d%% complete.")) %
+ entry.descname % percent)
+ .str();
+ }
+ } catch (...) {
+ }
+ }
+ }
+
+ // We will want some help with incomplete translations
+ if (percent <= 90) {
+ message = message + " " +
+ (boost::format(_("If you wish to help us translate, please visit %s")) %
+ "<font underline=1>widelands.org/wiki/TranslatingWidelands</font>")
+ .str();
+ }
+ // Make font a bit smaller so the link will fit at 800x600 resolution.
+ translation_info_.set_text(as_uifont(message, 12));
+}
+
void FullscreenMenuOptions::clicked_apply() {
end_modal<FullscreenMenuBase::MenuTarget>(FullscreenMenuBase::MenuTarget::kApplyOptions);
}
=== modified file 'src/ui_fsmenu/options.h'
--- src/ui_fsmenu/options.h 2017-09-11 08:09:07 +0000
+++ src/ui_fsmenu/options.h 2017-10-09 19:42:37 +0000
@@ -104,6 +104,7 @@
// Fills the language selection list
void add_languages_to_list(const std::string& current_locale);
+ void update_language_stats(bool include_system_lang);
// Saves the options and reloads the active tab
void clicked_apply();
@@ -112,8 +113,6 @@
uint32_t butw_;
uint32_t buth_;
uint32_t hmargin_;
- uint32_t tab_panel_width_;
- uint32_t column_width_;
uint32_t tab_panel_y_;
UI::Textarea title_;
@@ -123,6 +122,7 @@
// UI elements
UI::TabPanel tabs_;
UI::Box box_interface_;
+ UI::Box box_interface_left_;
UI::Box box_windows_;
UI::Box box_sound_;
UI::Box box_saving_;
@@ -134,6 +134,7 @@
UI::Checkbox fullscreen_;
UI::Checkbox inputgrab_;
UI::SpinBox sb_maxfps_;
+ UI::MultilineTextarea translation_info_;
// Windows options
UI::Checkbox snap_win_overlap_only_;
@@ -170,6 +171,26 @@
/// All supported screen resolutions.
std::vector<ScreenResolution> resolutions_;
+
+ // Data model for the entries in the language selection list.
+ struct LanguageEntry {
+ LanguageEntry(const std::string& init_localename,
+ const std::string& init_descname,
+ const std::string& init_sortname)
+ : localename(init_localename), descname(init_descname), sortname(init_sortname) {
+ }
+ LanguageEntry() : LanguageEntry("", "", "") {
+ }
+
+ bool operator<(const LanguageEntry& other) const {
+ return sortname < other.sortname;
+ }
+
+ std::string localename; // ISO code for the locale
+ std::string descname; // Native language name
+ std::string sortname; // ASCII Language name used for sorting
+ };
+ std::map<std::string, LanguageEntry> language_entries_;
};
#endif // end of include guard: WL_UI_FSMENU_OPTIONS_H
=== modified file 'utils/merge_and_push_translations.sh'
--- utils/merge_and_push_translations.sh 2017-05-19 07:41:26 +0000
+++ utils/merge_and_push_translations.sh 2017-10-09 19:42:37 +0000
@@ -67,6 +67,11 @@
# Update catalogues.
utils/buildcat.py
+
+# Update statistics.
+utils/update_translation_stats.py
+
+# Commit and push.
bzr commit -m "Fetched translations and updated catalogues."
bzr push lp:widelands
=== added file 'utils/update_translation_stats.py'
--- utils/update_translation_stats.py 1970-01-01 00:00:00 +0000
+++ utils/update_translation_stats.py 2017-10-09 19:42:37 +0000
@@ -0,0 +1,120 @@
+#!/usr/bin/env python
+# encoding: utf-8
+
+
+"""Uses pocount from the Translate Toolkit to write translation statistics to
+data/i18n/translation_stats.conf.
+
+You will need to have the Translate Toolkit installed:
+http://toolkit.translatehouse.org/
+
+For Debian-based Linux: sudo apt-get install translate-toolkit
+
+"""
+
+from collections import defaultdict
+from subprocess import call, check_output, CalledProcessError
+import os.path
+import re
+import subprocess
+import sys
+import traceback
+
+#############################################################################
+# Data Containers #
+#############################################################################
+
+
+class TranslationStats:
+ """Total source words and translated source words."""
+
+ def __init__(self):
+ self.total = 0
+ self.translated = 0
+
+
+#############################################################################
+# Main Loop #
+#############################################################################
+
+def generate_translation_stats(po_dir, output_file):
+ locale_stats = defaultdict(TranslationStats)
+
+ sys.stdout.write('Fetching translation stats ')
+
+ # We get errors for non-po files in the base po dir, so we have to walk
+ # the subdirs.
+ for subdir in sorted(os.listdir(po_dir), key=str.lower):
+ subdir = os.path.join(po_dir, subdir)
+ if not os.path.isdir(subdir):
+ continue
+
+ sys.stdout.write('.')
+ sys.stdout.flush()
+
+ try:
+ # We need shell=True, otherwise we get "No such file or directory".
+ stats_output = check_output(
+ ['pocount ' + subdir + ' --short-words'], stderr=subprocess.STDOUT, shell=True)
+ if 'ERROR' in stats_output:
+ print('\nError running pocount:\n' + stats_output.split('\n', 1)
+ [0]) + '\nAborted creating translation statistics.'
+ return False
+
+ except CalledProcessError:
+ print('Failed to run pocount:\n FILE: ' + po_dir +
+ '\n ' + stats_output.split('\n', 1)[1])
+ return False
+
+ result = stats_output.split('\n')
+
+ # Format provided by pocount:
+ # /home/<snip>/po/<textdomain>/<locale>.po source words: total: 1701 | 500t 0f 1201u | 29%t 0%f 70%u
+ regex_translated = re.compile(
+ '/\S+/(\w+)\.po\s+source words: total: (\d+)\t\| (\d+)t\t\d+f\t\d+u\t\| (\d+)%t\t\d+%f\t\d+%u')
+
+ for line in result:
+ match = regex_translated.match(line)
+ if match:
+ entry = TranslationStats()
+ locale = match.group(1)
+
+ if locale in locale_stats:
+ entry = locale_stats[locale]
+
+ entry.total = entry.total + int(match.group(2))
+ entry.translated = entry.translated + int(match.group(3))
+ locale_stats[locale] = entry
+
+ print('\n\nLocale\tTotal\tTranslated')
+ print('------\t-----\t----------')
+ result = ''
+ for locale in sorted(locale_stats.keys(), key=str.lower):
+ entry = locale_stats[locale]
+ print(locale + '\t' + str(entry.total) + '\t' + str(entry.translated))
+ result = result + '[' + locale + ']\n'
+ result = result + 'translated=' + str(entry.translated) + '\n'
+ result = result + 'total=' + str(entry.total) + '\n\n'
+
+ with open(output_file, 'w+') as destination:
+ destination.write(result[:-1]) # Strip the final \n
+ print('\nResult written to ' + output_file)
+ return True
+
+
+def main():
+ try:
+ po_dir = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '../po'))
+ output_file = os.path.abspath(os.path.join(
+ os.path.dirname(__file__), '../data/i18n/translation_stats.conf'))
+ result = generate_translation_stats(po_dir, output_file)
+ return result
+
+ except Exception:
+ print('Something went wrong:')
+ traceback.print_exc()
+ return 1
+
+if __name__ == '__main__':
+ sys.exit(main())
Follow ups
-
[Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: noreply, 2017-11-04
-
[Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: bunnybot, 2017-11-04
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-11-04
-
[Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: bunnybot, 2017-11-04
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-11-03
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: kaputtnik, 2017-11-03
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-11-03
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: kaputtnik, 2017-11-03
-
[Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: bunnybot, 2017-11-03
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-11-03
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: kaputtnik, 2017-11-02
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-11-02
-
[Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: bunnybot, 2017-11-02
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: kaputtnik, 2017-11-01
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-11-01
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: kaputtnik, 2017-11-01
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-11-01
-
[Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: bunnybot, 2017-10-31
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: kaputtnik, 2017-10-30
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-10-28
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-10-27
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: SirVer, 2017-10-24
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-10-24
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: SirVer, 2017-10-24
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: GunChleoc, 2017-10-24
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: SirVer, 2017-10-23
-
Re: [Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: kaputtnik, 2017-10-10
-
[Merge] lp:~widelands-dev/widelands/translation_stats into lp:widelands
From: bunnybot, 2017-10-10