From 012646f3f726c37d84a0de9554db3a1d80145274 Mon Sep 17 00:00:00 2001 From: Kevin Chabowski Date: Thu, 19 May 2011 21:41:56 +0200 Subject: Initial commit (uncoupled from sum2tools) --- .gitignore | 2 + README.md | 0 dotstr_edit.py | 445 +++++++++++++++++++++++++++++++++++ format_translations.sh | 9 + gettext_templates.sh | 3 + locale/de/LC_MESSAGES/dotstr_edit.po | 150 ++++++++++++ strfile.py | 30 +++ 7 files changed, 639 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100755 dotstr_edit.py create mode 100755 format_translations.sh create mode 100755 gettext_templates.sh create mode 100644 locale/de/LC_MESSAGES/dotstr_edit.po create mode 100644 strfile.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..cc66745 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +*.mo diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/dotstr_edit.py b/dotstr_edit.py new file mode 100755 index 0000000..25a333e --- /dev/null +++ b/dotstr_edit.py @@ -0,0 +1,445 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import strfile +import wx +import sys, os +import locale, gettext + +from wx.lib.mixins.listctrl import ListCtrlAutoWidthMixin + +def progdir(): + """Get the path to the directory of this file""" + return os.path.abspath(os.path.dirname(sys.argv[0])) + +class TransDictListCtrl(wx.ListCtrl, ListCtrlAutoWidthMixin): + """ListCtrl for a translation dictionary""" + def __init__(self, parent): + wx.ListCtrl.__init__(self, parent, -1, style=wx.LC_REPORT | wx.SUNKEN_BORDER | wx.LC_VIRTUAL | wx.LC_SINGLE_SEL) + ListCtrlAutoWidthMixin.__init__(self) + self.InsertColumn(0, _("Identification"), width=250) + self.InsertColumn(1, _("Text")) + self.dict = {} + self.update() + + def update(self, onlyone=None): + """ + Update the list. + + If onlyone is set, only the translation with the key = onlyone will be updated + If not, evrything will be updated + """ + if onlyone is None: + self.DeleteAllItems() + self.SetItemCount(len(self.dict)) + self.RefreshItems(0,len(self.dict)) + else: + key, val = onlyone + self.dict[key] = val + self.RefreshItem(self.dict.keys().index(key)) + + def set_dict(self, d): + """Set the translation dictionary""" + self.dict = d + self.update() + + def get_seclection(self): + """ + Get the key of the selected translation. + + If no translation is selected, an empty string will be returned + """ + index = self.GetNextItem(-1, wx.LIST_NEXT_ALL, wx.LIST_STATE_SELECTED) + return "" if index == -1 else self.dict.keys()[index] + + def OnGetItemText(self, item, col): + """Basic implementation of the LC_VIRTUAL mechanism""" + if col == 0: + return self.dict.keys()[item] + else: + return self.dict.values()[item] + +class new_entry_dialog(wx.Dialog): + """ + Dialog that prompts the user for a new translation key + """ + def __init__(self, parent): + # Layout stuff + wx.Dialog.__init__(self, parent, title=_("New entry"), size=(500,-1)) + + vbox = wx.BoxSizer(wx.VERTICAL) + vbox.Add(wx.StaticText(self, label=_("Name of your new entry:")), 0, wx.EXPAND | wx.ALL, 5) + + hbox = wx.BoxSizer(wx.HORIZONTAL) + self.part1 = wx.TextCtrl(self) + self.part2 = wx.TextCtrl(self) + hbox.Add(self.part1, 2, wx.EXPAND, 0) + hbox.Add(wx.StaticText(self, label=":"), 0, wx.ALIGN_CENTER_VERTICAL | wx.RIGHT | wx.LEFT, 5) + hbox.Add(self.part2, 3, wx.EXPAND, 0) + hbox.SetMinSize((500,-1)) + vbox.Add(hbox, 0, wx.EXPAND | wx.ALL, 5) + vbox.Add(self.CreateButtonSizer(wx.OK | wx.CANCEL), 0, wx.EXPAND | wx.ALL, 5) + + self.SetSizer(vbox) + vbox.Fit(self) + + self.Bind(wx.EVT_BUTTON, self.on_ok, id=wx.OK) + self.Bind(wx.EVT_BUTTON, self.on_cancel, id=wx.CANCEL) + self.Bind(wx.EVT_CLOSE, self.on_cancel) + + def get_identifier(self): + """ + This will return the key/identifier. + """ + allowed_chars = map(chr, range(ord("A"), ord("Z")+1) + range(ord("a"), ord("z")+1))+["_","-"] + part1 = "".join(filter(lambda c: c in allowed_chars, self.part1.GetValue())) + part2 = "".join(filter(lambda c: c in allowed_chars, self.part2.GetValue())) + + return part1 + ":" + part2 + + def on_ok(self, event): + self.EndModal(wx.ID_OK) + + def on_cancel(self, event): + self.EndModal(wx.ID_CANCEL) + +class editor_frame(wx.Frame): + """ + The Frame of the editor. + """ + def __init__(self): + filter_label = _("&Filter") + self.dict = {} + self.changed = False + self.filename = "" + + # GUI stuff + the_arts = wx.ArtProvider() + wx.Frame.__init__(self, None, title=_(".str Editor"), size=(500,600)) + + # menubar + menubar = wx.MenuBar() + + m_file = wx.Menu() + m_file.AppendItem(wx.MenuItem(m_file, wx.ID_NEW, _("&New"))) + m_file.AppendItem(wx.MenuItem(m_file, wx.ID_OPEN, _("&Open"))) + m_file.AppendItem(wx.MenuItem(m_file, wx.ID_SEPARATOR)) + m_file.AppendItem(wx.MenuItem(m_file, wx.ID_SAVE, _("&Save"))) + m_file.AppendItem(wx.MenuItem(m_file, wx.ID_SAVEAS, _("Save &As"))) + m_file.AppendItem(wx.MenuItem(m_file, wx.ID_SEPARATOR)) + m_file.AppendItem(wx.MenuItem(m_file, wx.ID_EXIT, _("&Exit"))) + + m_help = wx.Menu() + m_help.AppendItem(wx.MenuItem(m_help, wx.ID_ABOUT, _("&About"))) + + menubar.Append(m_file, _("&File")) + menubar.Append(m_help, _("&Help")) + + self.SetMenuBar(menubar) + + # toolbar + toolbar = self.CreateToolBar() + toolbar.AddLabelTool(wx.ID_NEW, _("New"), the_arts.GetBitmap(wx.ART_NEW, wx.ART_TOOLBAR)) + toolbar.AddLabelTool(wx.ID_OPEN, _("Open"), the_arts.GetBitmap(wx.ART_FILE_OPEN, wx.ART_TOOLBAR)) + toolbar.AddLabelTool(wx.ID_SAVE, _("Save"), the_arts.GetBitmap(wx.ART_FILE_SAVE, wx.ART_TOOLBAR)) + toolbar.Realize() + + # shortcuts + jump_to_filter_id = wx.NewId() + filter_shortcut_char = ord(filter_label[filter_label.find("&")+1].lower()) + shortcuts = wx.AcceleratorTable([ + (wx.ACCEL_CTRL, ord('s'), wx.ID_SAVE), + (wx.ACCEL_CTRL, ord('o'), wx.ID_OPEN), + (wx.ACCEL_CTRL, ord('n'), wx.ID_NEW), + (wx.ACCEL_CTRL, ord('q'), wx.ID_EXIT), + (wx.ACCEL_CTRL, filter_shortcut_char, jump_to_filter_id) + ]) + self.SetAcceleratorTable(shortcuts) + + # the "real" GUI + self.mainpanel = wx.Panel(self, -1) + vbox = wx.BoxSizer(wx.VERTICAL) + + filter_hbox = wx.BoxSizer(wx.HORIZONTAL) + self.input_filter = wx.TextCtrl(self.mainpanel) + filter_hbox.Add(wx.StaticText(self.mainpanel, label=filter_label), 0, wx.RIGHT | wx.ALIGN_CENTER_VERTICAL, 5) + filter_hbox.Add(self.input_filter, 1, wx.EXPAND, 0) + vbox.Add(filter_hbox, 0, wx.EXPAND | wx.ALL, 5) + + trl_hbox = wx.BoxSizer(wx.HORIZONTAL) + self.transl_list = TransDictListCtrl(self.mainpanel) + + trl_vbox = wx.BoxSizer(wx.VERTICAL) + trl_add_btn = wx.BitmapButton(self.mainpanel, bitmap=the_arts.GetBitmap(wx.ART_ADD_BOOKMARK, wx.ART_BUTTON)) + trl_del_btn = wx.BitmapButton(self.mainpanel, bitmap=the_arts.GetBitmap(wx.ART_DEL_BOOKMARK, wx.ART_BUTTON)) + trl_vbox.Add(trl_add_btn, 0, wx.EXPAND | wx.BOTTOM, 5) + trl_vbox.Add(trl_del_btn, 0, wx.EXPAND, 0) + + trl_hbox.Add(self.transl_list, 1, wx.EXPAND, wx.RIGHT, 5) + trl_hbox.Add(trl_vbox, 0, wx.EXPAND, 0) + vbox.Add(trl_hbox, 3, wx.EXPAND | wx.ALL, 5) + + vbox.Add(wx.StaticLine(self.mainpanel, style=wx.LI_HORIZONTAL),.0, wx.EXPAND | wx.ALL, 5) + + vbox.Add(wx.StaticText(self.mainpanel, label=_("Text:")), 0, wx.EXPAND | wx.ALL, 5) + self.trans_text_ctrl = wx.TextCtrl(self.mainpanel, style=wx.TE_MULTILINE) + vbox.Add(self.trans_text_ctrl, 2, wx.EXPAND | wx.ALL, 5) + + self.mainpanel.SetSizer(vbox) + + # Binding events + self.Bind(wx.EVT_MENU, self.on_new, id=wx.ID_NEW) + self.Bind(wx.EVT_MENU, self.on_open, id=wx.ID_OPEN) + self.Bind(wx.EVT_MENU, self.on_save, id=wx.ID_SAVE) + self.Bind(wx.EVT_MENU, self.on_saveas, id=wx.ID_SAVEAS) + self.Bind(wx.EVT_MENU, self.on_close, id=wx.ID_EXIT) + self.Bind(wx.EVT_MENU, self.on_about, id=wx.ID_ABOUT) + self.Bind(wx.EVT_TEXT, self.on_filter, id=self.input_filter.GetId()) + self.Bind(wx.EVT_TEXT, self.on_textedit, id=self.trans_text_ctrl.GetId()) + self.Bind(wx.EVT_BUTTON, self.on_add, id=trl_add_btn.GetId()) + self.Bind(wx.EVT_BUTTON, self.on_del, id=trl_del_btn.GetId()) + self.Bind(wx.EVT_MENU, self.on_jmp_filter, id=jump_to_filter_id) + self.Bind(wx.EVT_CLOSE, self.on_close) + self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_listsel, id=self.transl_list.GetId()) + self.Bind(wx.EVT_LIST_ITEM_DESELECTED, self.on_listunsel, id=self.transl_list.GetId()) + + def really_discard(self): + """ + If the content was modified, the user will be asked if he really wants to discard the changes + + This will return True if the calling function can continue normal work. + """ + if self.changed: + dialog = wx.MessageDialog(None, + message=_("You did not save your changes. Continue?"), + caption=_("Unsaved changes"), + style=wx.ICON_QUESTION | wx.YES_NO) + user_ret = dialog.ShowModal() + dialog.Destroy() + return user_ret == wx.ID_YES + return True + + def populate_list(self, autoselect=None): + """ + Populating the translation list with the filtered self.dict + + If autoselect is not None, the given translation will be selected and focussed. + """ + filter_str = self.input_filter.GetValue().lower() + f_dict = {} + for key in self.dict.iterkeys(): + if filter_str != '': + if (filter_str not in key.lower()) and (filter_str not in self.dict[key].lower()): + continue + f_dict[key] = self.dict[key] + self.transl_list.set_dict(f_dict) + self.trans_text_ctrl.SetValue("") + if autoselect is not None: + self.transl_list.Select(f_dict.keys().index(autoselect)) + self.transl_list.Focus(f_dict.keys().index(autoselect)) + + def form_init(self): + """ + IInitializes / clears all formulars + """ + self.populate_list() + self.input_filter.SetValue("") + + def on_close(self, event): + if self.really_discard(): + self.Destroy() + + def on_new(self, event): + if self.really_discard(): + self.dict = {} + self.changed = False + self.filename = "" + self.form_init() + + def on_open(self, event): + if self.really_discard(): + new_fn = "" + dialog = wx.FileDialog(None, _("Choose a file"), wildcard=fd_wildcard, style=wx.FD_OPEN | wx.FD_FILE_MUST_EXIST) + if dialog.ShowModal() == wx.ID_OK: + new_fn = dialog.GetPath() + dialog.Destroy() + + if new_fn != "": + try: + fp = open(new_fn, "rb") + temp_dict = strfile.dict_parse(fp.read()) + self.dict = temp_dict + fp.close() + self.filename = new_fn + self.changed = False + self.form_init() + except: + del dialog + dialog = wx.MessageDialog(None, + message=_("Could not open file.\nUsually that means that the file is invalid or you do not have enough privileges."), + caption=_("Could not open file"), + style=wx.ICON_ERROR | wx.OK) + dialog.ShowModal() + dialog.Destroy() + + def save_file(self, force_path=False): + saveto = "" + if force_path or self.filename=='': + if self.filename == "": + dialog = wx.FileDialog(None, + message=_("Save to"), + wildcard=fd_wildcard, + style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) + else: + def_dir, def_file = os.path.split(self.filename) + dialog = wx.FileDialog(None, + message=_("Save to"), + wildcard=fd_wildcard, + defaultDir=def_dir, + defaultFile=def_file, + style=wx.FD_SAVE | wx.FD_OVERWRITE_PROMPT) + if dialog.ShowModal() == wx.ID_OK: + saveto = dialog.GetPath() + else: + saveto = "" + dialog.Destroy() + else: + saveto = self.filename + if saveto != "": + try: + fp = open(saveto, "w") + strfile.dict_gen(self.dict, fp) + fp.close() + except: + err_dialog = wx.MessageDialog( + None, + message=_("Can not write to file \"%s\".\nUsually that means that you do not have enough privileges or you ran out of disc memory.") % saveto, + caption=_("Can not save file."), + style=wx.ICON_ERROR | wx.OK) + err_dialog.ShowModal() + err_dialog.Close() + self.changed = False + + def on_save(self, event): + self.save_file() + + def on_saveas(self, event): + self.save_file(True) + + def on_about(self, event): + description = _(".str Editor is a tool for editing the .str files of EA's BFME2") + licence = u"""Copyright (c) 2010-2011 \"Die Völker Mittelerdes\" Modding Crew + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.""" + info = wx.AboutDialogInfo() + info.SetName(_('.str Editor')) + info.SetVersion('0.1') + info.SetDescription(description) + info.SetCopyright(u'(C) 2010-2011 \"Die Völker Mittelerdes\" Modding Crew') + info.SetLicence(licence) + info.AddDeveloper('Kevin Chabowski') + + wx.AboutBox(info) + + def on_listsel(self, event): + self.trans_text_ctrl.SetValue(strfile.unescape(self.dict[self.transl_list.get_seclection()])) + + def on_listunsel(self, event): + self.trans_text_ctrl.SetValue("") + + def on_filter(self, event): + if self.input_filter.GetValue() != "": + self.populate_list() + if len(self.transl_list.dict) == 0 and self.input_filter.GetValue() != "": + self.input_filter.SetBackgroundColour(wx.Colour(255,100,100)) + else: + self.input_filter.SetBackgroundColour(wx.NullColour) + + def on_textedit(self, event): + key = self.transl_list.get_seclection() + if key != "": + newval = strfile.escape(self.trans_text_ctrl.GetValue()) + self.dict[key] = newval + self.transl_list.update((key, newval)) + self.changed = True + + def on_add(self, event): + addthis = ":" + while addthis == ":": + dialog = new_entry_dialog(None) + if dialog.ShowModal() != wx.ID_OK: + dialog.Destroy() + return + addthis = dialog.get_identifier() + dialog.Destroy() + if addthis in self.dict.keys(): + addthis = ':' + del dialog + dialog = wx.MessageDialog( + None, + message=_("This name is already in use. Choose another one."), + caption=_("Invalid name"), + style=wx.ICON_WARNING | wx.OK + ) + dialog.ShowModal() + dialog.Destroy() + del dialog + self.changed = True + self.dict[addthis] = "" + self.input_filter.SetValue("") + self.populate_list(addthis) + + + def on_del(self, event): + delthis = self.transl_list.get_seclection() + if delthis != "": + del self.dict[delthis] + self.changed = True + self.populate_list() + + def on_jmp_filter(self, event): + self.input_filter.SetFocus() + +class dotstr_edit_app(wx.App): + def OnInit(self): + app_frame = editor_frame() + app_frame.Show() + self.SetTopWindow(app_frame) + return True + +if __name__ == '__main__': + # init localisation + if os.name == 'nt': + # windows hack for locale setting + lang = os.getenv('LANG') + if lang is None: + default_lang, default_enc = locale.getdefaultlocale() + if default_lang: + lang = default_lang + if lang: + os.environ['LANG'] = lang + locale.setlocale(locale.LC_ALL, '') + translator = gettext.translation('dotstr_edit', os.path.join(progdir(), 'locale'), fallback=True) + translator.install(True) + + fd_wildcard = _("str File")+"|*.str|*.*|*.*" + + # Start application + app = dotstr_edit_app() + app.MainLoop() + diff --git a/format_translations.sh b/format_translations.sh new file mode 100755 index 0000000..f0c4536 --- /dev/null +++ b/format_translations.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash + +for locale_dir in locale/*; do + for pofile in $locale_dir/LC_MESSAGES/*.po; do + mofile=`echo $pofile | sed -n "s/\\.po/\\.mo/p"`; + echo "$pofile => $mofile"; + msgfmt "$pofile" -o "$mofile"; + done; +done; diff --git a/gettext_templates.sh b/gettext_templates.sh new file mode 100755 index 0000000..dc28cab --- /dev/null +++ b/gettext_templates.sh @@ -0,0 +1,3 @@ +#!/usr/bin/env bash + +xgettext -d dotstr_edit -s -L Python -o dotstr_edit.pot dotstr_edit.py diff --git a/locale/de/LC_MESSAGES/dotstr_edit.po b/locale/de/LC_MESSAGES/dotstr_edit.po new file mode 100644 index 0000000..6d20941 --- /dev/null +++ b/locale/de/LC_MESSAGES/dotstr_edit.po @@ -0,0 +1,150 @@ +# German translations for sum package. +# Copyright (C) 2010 THE sum'S COPYRIGHT HOLDER +# This file is distributed under the same license as the sum package. +# Automatically generated, 2010. +# +msgid "" +msgstr "" +"Project-Id-Version: sum 2tools\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2010-11-28 00:57+0100\n" +"PO-Revision-Date: 2010-11-28 01:10+0100\n" +"Last-Translator: Kevin Chabowski \n" +"Language-Team: none\n" +"Language: de\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +#: dotstr_edit.py:132 +msgid "&About" +msgstr "&Über" + +#: dotstr_edit.py:129 +msgid "&Exit" +msgstr "S&chließen" + +#: dotstr_edit.py:134 +msgid "&File" +msgstr "&Datei" + +#: dotstr_edit.py:110 +msgid "&Filter" +msgstr "&Filter" + +#: dotstr_edit.py:135 +msgid "&Help" +msgstr "&Hilfe" + +#: dotstr_edit.py:123 +msgid "&New" +msgstr "&Neu" + +#: dotstr_edit.py:124 +msgid "&Open" +msgstr "&Öffnen" + +#: dotstr_edit.py:126 +msgid "&Save" +msgstr "&Speichern" + +#: dotstr_edit.py:117 +#: dotstr_edit.py:335 +msgid ".str Editor" +msgstr ".str Editor" + +#: dotstr_edit.py:332 +msgid ".str Editor is a tool for editing the .str files of EA's BFME2" +msgstr ".str Editor ist ein Tool zum bearbeiten der .str Dateien von EA's SuM2" + +#: dotstr_edit.py:319 +msgid "Can not save file." +msgstr "Kann Datei nicht speichern." + +#: dotstr_edit.py:318 +#, python-format +msgid "" +"Can not write to file \"%s\".\n" +"Usually that means that you do not have enough privileges or you ran out of disc memory." +msgstr "" +"Kann nicht auf Datei \"%s\" schreiben.\n" +"Normalerweise bedeutet dies, dass du nicht genügend Privilegien oder nicht genug Speicherplatz hast." + +#: dotstr_edit.py:264 +msgid "Choose a file" +msgstr "Wähle Datei aus" + +#: dotstr_edit.py:282 +msgid "Could not open file" +msgstr "Kann Datei nicht öffnen" + +#: dotstr_edit.py:281 +msgid "" +"Could not open file.\n" +"Usually that means that the file is invalid or you do not have enough privileges." +msgstr "" +"Kann Datei nicht öffnen.\n" +"Normalerweise bedeutet dies, dass du nicht genügend Privilegien hast." + +#: dotstr_edit.py:20 +msgid "Identification" +msgstr "Identifikation" + +#: dotstr_edit.py:381 +msgid "Invalid name" +msgstr "Ungültiger Name" + +#: dotstr_edit.py:70 +msgid "Name of your new entry:" +msgstr "Name deines neuen Eintrages:" + +#: dotstr_edit.py:141 +msgid "New" +msgstr "Neu" + +#: dotstr_edit.py:67 +msgid "New entry" +msgstr "Neuer Eintrag" + +#: dotstr_edit.py:142 +msgid "Open" +msgstr "Öffnen" + +#: dotstr_edit.py:143 +msgid "Save" +msgstr "Speichern" + +#: dotstr_edit.py:127 +msgid "Save &As" +msgstr "Spechern &unter" + +#: dotstr_edit.py:292 +#: dotstr_edit.py:298 +msgid "Save to" +msgstr "Spechern unter" + +#: dotstr_edit.py:21 +msgid "Text" +msgstr "Text" + +#: dotstr_edit.py:183 +msgid "Text:" +msgstr "Text:" + +#: dotstr_edit.py:380 +msgid "This name is already in use. Choose another one." +msgstr "Dieser Name wird bereits benutzt. Wähle einen anderen." + +#: dotstr_edit.py:214 +msgid "Unsaved changes" +msgstr "Ungespeicherte Änderungen" + +#: dotstr_edit.py:213 +msgid "You did not save your changes. Continue?" +msgstr "Du hast deine Änderungen nicht gespeichert. Fortfahren?" + +#: dotstr_edit.py:425 +msgid "str File" +msgstr "str Datei" + diff --git a/strfile.py b/strfile.py new file mode 100644 index 0000000..b70e8c4 --- /dev/null +++ b/strfile.py @@ -0,0 +1,30 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import os, re + +lotr_str_regex = re.compile(r'([A-Z]*\:.*?)\"(.*?)\"(?:.*?)END',re.DOTALL) + +def dict_parse(rawdata): + global lotr_str_regex + rawdata = rawdata.decode("latin-1") + + dictionary = {} + + for match, string in lotr_str_regex.findall(rawdata): + match = match.strip() + string = string.strip() + + dictionary[match] = string + return dictionary + +def dict_gen(dictionary, fp): + for match in dictionary: + fp.write("%s\n\"%s\"\nEND\n\n" % (match.encode('latin-1'), + dictionary[match].encode('latin-1'))) + +def escape(text): + return text.replace("\n", "\\n") + +def unescape(text): + return text.replace("\\n", "\n") -- cgit v1.2.3-54-g00ecf