def hotCount(st): '''Counts the number of words in a string. ARGUMENTS: str st: count the number of words in this string RETURNS: int: the number of words in st''' startpos = long() nextwd = Boundary() lc = Locale() lc.Language = 'en' numwords = 1 mystartpos = 1 brk = smgr.createInstanceWithContext('com.sun.star.i18n.BreakIterator', ctx) nextwd = brk.nextWord(st, startpos, lc, WORD_COUNT) while nextwd.startPos != nextwd.endPos: numwords += 1 nw = nextwd.startPos nextwd = brk.nextWord(st, nw, lc, WORD_COUNT) return numwords
def get_ui_locale(ctx): """ get UI locale as css.lang.Locale struct. """ loc = get_config_value(ctx, "/org.openoffice.Setup/L10N", "ooLocale") if "-" in loc: parts = loc.split("-") locale = Locale(parts[0], parts[1], "") else: locale = Locale(loc, "", "") return locale
def _getCurrentLocale(self): parts = self._getConfiguration("/org.openoffice.Setup/L10N").getByName("ooLocale").split("-") locale = Locale(parts[0], "", "") if len(parts) == 2: locale.Country = parts[1] else: service = self.ctx.ServiceManager.createInstance("com.sun.star.i18n.LocaleData") locale.Country = service.getLanguageCountryInfo(locale).Country return locale
def queryLocale(self, prop, loc): if loc != None: a = loc.split("-") if len(a) == 1: return Locale(a[0], "", "") if len(a) == 2: return Locale(a[0], a[1], "") else: return Locale(a[0], a[1], a[2]) locale = prop.getPropertyValue("CharLocale") if locale != None and locale.Language != "zxx": return locale return Locale("en", "US", "")
def __addLocale(self, locales, language): matchingMappings = self.__bcpToOOoMap[language] for bcpMapping in matchingMappings: locales.append( Locale(bcpMapping.loLanguage, bcpMapping.loRegion, "")) if language in self.__bcpAdvertiseWithoutCountry: locales.append(Locale(language, "", "")) return if len(matchingMappings) == 0: if len(language) <= 3: # assume this is ISO 639-1 or ISO 639-3 code locales.append(Locale(language, "", "")) else: locales.append(Locale("qlt", "", language))
def treatmentTable(doc, text, cursor, treatments, descriptions, units, post_values, dates, modifiers): table = createTable(doc, text, cursor, len(treatments)) counter = 2 for treatment, description, unit, post_value, date, modifier in zip(treatments, descriptions, units, post_values, dates, modifiers): if modifier == '14' or modifier == '13' or modifier == '10': insertTextIntoCell(table, "C" + str(counter), str(treatment.zfill(3) + " (0" + modifier + ")")) elif modifier == '6' or modifier == '8' or modifier == '9': insertTextIntoCell(table, "C" + str(counter), str(treatment.zfill(3) + " (00" + modifier + ")")) else: insertTextIntoCell(table, "C" + str(counter), treatment.zfill(3)) insertTextIntoCell(table, "A" + str(counter), date) insertTextIntoCell(table, "B" + str(counter), description) insertTextIntoCell(table, "D" + str(counter), unit) insertTextIntoCell(table, "E" + str(counter), post_value) counter += 1 cell_sum = table.getCellByName("E" + str(counter)) cell_sum.setFormula("=sum <E2:E" + str(counter - 1) + ">") cRange = table.getCellRangeByName("E2:E" + str(counter) ) xNumberFormats = doc.NumberFormats xLocale = Locale('en', 'US', '') format_string = '#,##0.00#'#[$€-407];[RED]-#,##0.00 [$€-407]' key = xNumberFormats.queryKey(format_string, xLocale, True) key = xNumberFormats.addNew(format_string, xLocale) cRange.NumberFormat = key cRange.setPropertyValue( "ParaAdjust", RIGHT ) # NumForms = doc.getNumberFormats() # dateFormatString = "YYYY/MM/DD\\ HH:MM:SS" # DateKey = NumForms.queryKey(dateFormatString, sLocale, True) # cell_sum.NumberFormat = DateKey return doc, text
def __init__(self, sWord, lSugg): try: self.sWord = sWord self.lSugg = lSugg self.xLocale = Locale('fr', 'FR', '') except: traceback.print_exc()
def mousePressed( self, mouseevent): # グリッドコントロールをクリックした時。コントロールモデルにはNameプロパティはない。 xscriptcontext, dateformat, formatstring = self.args gridcontrol = mouseevent.Source # グリッドコントロールを取得。 if mouseevent.Buttons == MouseButton.LEFT: if mouseevent.ClickCount == 2: # ダブルクリックの時。 doc = xscriptcontext.getDocument() selection = doc.getCurrentSelection() # シート上で選択しているオブジェクトを取得。 if selection.supportsService( "com.sun.star.sheet.SheetCell"): # 選択オブジェクトがセルの時。 rowindexes = getSelectedRowIndexes( gridcontrol ) # グリッドコントロールの選択行インデックスを返す。昇順で返す。負数のインデックスがある時は要素をクリアする。 if rowindexes: datetxt = gridcontrol.getModel().getPropertyValue( "GridDataModel").getCellData( 1, rowindexes[0]) # 選択行の日付文字列を取得。 selectedday = datetime.strptime( datetxt, dateformat) # 現在の最初のdatetimeオブジェクトを取得。 selection.setFormula( selectedday.isoformat()) # セルに式として代入。 numberformats = doc.getNumberFormats( ) # ドキュメントのフォーマット一覧を取得。デフォルトのフォーマット一覧はCalcの書式→セル→数値でみれる。 if formatstring is not None: # 書式が与えられている時。 locale = Locale( Language="ja", Country="JP" ) # フォーマット一覧をくくる言語と国を設定。インストールしていないUIの言語でもよい。。 formatkey = numberformats.queryKey( formatstring, locale, True ) # formatstringが既存のフォーマット一覧にあるか調べて取得。第3引数のブーリアンは意味はないはず。 if formatkey == -1: # デフォルトのフォーマットにformatstringがないとき。 formatkey = numberformats.addNew( formatstring, locale) # フォーマット一覧に追加する。保存はドキュメントごと。 selection.setPropertyValue("NumberFormat", formatkey) # セルの書式を設定。 for menuid in range(1, self.gridpopupmenu.getItemCount() + 1): # ポップアップメニューを走査する。 itemtext = self.gridpopupmenu.getItemText( menuid) # 文字列にはショートカットキーがついてくる。 if itemtext.startswith("セル入力で閉じる"): if self.gridpopupmenu.isItemChecked( menuid): # 選択項目にチェックが入っている時。 self.dialogframe.close(True) else: controller = doc.getCurrentController( ) # 現在のコントローラを取得。 sheet = controller.getActiveSheet() celladdress = selection.getCellAddress() nextcell = sheet[celladdress.Row + 1, celladdress.Column] # 下のセルを取得。 controller.select(nextcell) # 下のセルを選択。 break elif mouseevent.Buttons == MouseButton.RIGHT: # 右ボタンクリックの時。mouseevent.PopupTriggerではサブジェクトによってはTrueにならないので使わない。 pos = Rectangle(mouseevent.X, mouseevent.Y, 0, 0) # ポップアップメニューを表示させる起点。 self.gridpopupmenu.execute(gridcontrol.getPeer(), pos, PopupMenuDirection.EXECUTE_DEFAULT ) # ポップアップメニューを表示させる。引数は親ピア、位置、方向
def convertKanaFULLWIDTH(transliteration, kanatxt): # カナ名を半角からスペースを削除して全角にして返す。 transliteration.loadModuleNew((HALFWIDTH_FULLWIDTH, ), Locale(Language="ja", Country="JP")) kanatxt = kanatxt.replace(" ", "") # 半角空白を除去してカナ名を取得。 return transliteration.transliterate(kanatxt, 0, len(kanatxt), [])[0] # カナを全角に変換。
def __init__(self, ctx, *args): try: self.ctx = ctx self.sServiceName = "com.sun.star.linguistic2.SpellChecker" self.sImplementationName = "net.grammalecte.graphspell" self.tSupportedServiceNames = (self.sServiceName, ) self.xSvMgr = ctx.ServiceManager self.locales = tuple([Locale(t[0], t[1], t[2]) for t in lLocale]) self.xSettingNode = helpers.getConfigSetting( "/org.openoffice.Lightproof_grammalecte/Other/", False) self.xOptionNode = self.xSettingNode.getByName("o_fr") sMainDicName = self.xOptionNode.getPropertyValue("main_dic_name") personal_dic = "" if self.xOptionNode.getPropertyValue("use_personal_dic"): sPersonalDicJSON = self.xOptionNode.getPropertyValue( "personal_dic") if sPersonalDicJSON: try: personal_dic = json.loads(sPersonalDicJSON) except: print("Graphspell: wrong personal_dic") traceback.print_exc() self.oGraphspell = SpellChecker("fr", "fr-" + sMainDicName + ".json", "", personal_dic) self.loadHunspell() # print("Graphspell: init done") except: print("Graphspell: init failed") traceback.print_exc()
def listSpellChecker(self): xLinguServiceManager = self.xSvMgr.createInstance( "com.sun.star.linguistic2.LinguServiceManager") lService = xLinguServiceManager.getAvailableServices( 'com.sun.star.linguistic2.SpellChecker', Locale("fr", "MC", "")) for sSpellchecker in lService: print(repr(sSpellchecker))
def createFormatKey(formatstring): # formatstringの書式はLocalによって異なる。 numberformats = doc.getNumberFormats() # ドキュメントのフォーマット一覧を取得。デフォルトのフォーマット一覧はCalcの書式→セル→数値でみれる。 locale = Locale(Language="ja", Country="JP") # フォーマット一覧をくくる言語と国を設定。インストールしていないUIの言語でもよい。。 formatkey = numberformats.queryKey(formatstring, locale, True) # formatstringが既存のフォーマット一覧にあるか調べて取得。第3引数のブーリアンは意味はないはず。 if formatkey == -1: # デフォルトのフォーマットにformatstringがないとき。 formatkey = numberformats.addNew(formatstring, locale) # フォーマット一覧に追加する。保存はドキュメントごと。 return formatkey
def changeLanguage(self, lang): if lang in self.custom_i18n.keys(): myi18n = self.custom_i18n[lang] else: raise RuntimeError('Unsupported language: %s' % lang) for key in list(self.i18n.keys()): del self.i18n[key] for key in myi18n: self.i18n[key] = myi18n[key] if lang in self.languageStrings: language, country = self.languageStrings[lang] loc = Locale() loc.Language = language loc.Country = country self._document.CharLocale = loc
def __init__ (self, ctx, *args): self.ctx = ctx self.ServiceName = "com.sun.star.linguistic2.Proofreader" self.ImplementationName = "org.openoffice.comp.pyuno.Lightproof." + gce.pkg self.SupportedServiceNames = (self.ServiceName, ) self.locales = [] for i in gce.locales: l = gce.locales[i] self.locales.append(Locale(l[0], l[1], l[2])) self.locales = tuple(self.locales) # debug #helpers.startConsole() # init gce.load("Writer", "nInt") # GC options #xContext = uno.getComponentContext() #opt_handler.load(xContext) dOpt = Options.loadOptions("${lang}") gce.setOptions(dOpt) # dictionaries options self.loadUserDictionaries() # underlining options self.setWriterUnderliningStyle() # regex for special chars that modify positioning self.zSpecialChars = re.compile("[\U00010000-\U0001fbff]") # store for results of big paragraphs self.dResult = {} self.nMaxRes = 1500 self.lLastRes = deque(maxlen=self.nMaxRes) self.nRes = 0
def fullwidth_halfwidth(xscriptcontext): ctx = xscriptcontext.getComponentContext() # コンポーネントコンテクストの取得。 smgr = ctx.getServiceManager() # サービスマネージャーの取得。 transliteration = smgr.createInstanceWithContext( "com.sun.star.i18n.Transliteration", ctx) # Transliteration。 transliteration.loadModuleNew((FULLWIDTH_HALFWIDTH, ), Locale(Language="ja", Country="JP")) # 全角を半角に変換するモジュール。 return transliteration
def changeLanguage(self, lang): if lang in self.custom_i18n.keys(): myi18n = self.custom_i18n[lang] else: raise RuntimeError('Unsupported language: %s' % lang) for key in list(self.i18n.keys()): del self.i18n[key] for key in myi18n: self.i18n[key] = myi18n[key] self._currentLanguage = lang if lang in self.languageStrings: language, country = self.languageStrings[lang] loc = Locale() loc.Language = language loc.Country = country self._document.CharLocale = loc
def get_or_create_number_format(doc=None, new_format=''): if doc is None: doc = get_current_doc() nf = doc.NumberFormats l = Locale() key = nf.queryKey(new_format, l, False) if key == -1: key = nf.addNew(new_format, l) return key
def __init__(self, ctx, *args): self.ctx = ctx self.ServiceName = "com.sun.star.linguistic2.Proofreader" self.ImplementationName = "org.libreoffice.comp.pyuno.Lightproof." + pkg self.SupportedServiceNames = (self.ServiceName, ) self.locales = [] for i in locales: l = locales[i] self.locales += [Locale(l[0], l[1], l[2])] self.locales = tuple(self.locales)
def get_current_locale(ctx): """ Get current locale. """ config = get_config(ctx, "/org.openoffice.Setup/L10N") locale = config.getPropertyValue("ooLocale") parts = locale.split("-") lang = parts[0] country = "" if len(parts) == 2: country = parts[1] return Locale(lang, country, "")
def find_number_format_style( oFormats: UnoService, format_id: NumberFormat, oLocale: Locale = Locale()) -> int: """ @param oFormats: the formats @param format_id: a NumberFormat @param oLocale: the locale @return: the id of the format """ return oFormats.getStandardFormat(format_id, oLocale)
def spell(self, lang, word): ''' None if word is spelled correctly using lang. Otherwise, if available, proposals for spelling alternatives will be returned. ''' loc = Locale(lang[0:2], lang[3:5], '') sug = self.spellchecker.spell(word, loc, ()) if sug: return sug.getAlternatives() else: return None
def fill_cell_with_data(doc, data, cell): """Fills a single cell with given data. Before the data is stored in the cell of an worksheet, the type of the data is checked. All necessary conversion and type casts are done before the value of the cell is set.""" NumberFormat = doc.getNumberFormats() LocalSettings = Locale() LocalSettings.Language = 'de' if not data: cell.String = '' elif type(data) == str: cell.String = data elif type(data) == Arrow: # write datetime into cell cell.String = data.format('DD.MM.YYYY HH:mm:ss') # set number format for cell FormatString = 'TT.MM.JJJJ HH:MM:SS' NumberFormatID = NumberFormat.queryKey(FormatString, LocalSettings, True) # check whether a value was found for the requested format (-1 == no value) if NumberFormatID == -1: NumberFormatID = NumberFormat.addNew(FormatString, LocalSettings) cell.NumberFormat = NumberFormatID elif type(data) == timedelta: # write datetime into cell cell.String = str(data) # set number format for cell FormatString = 'HH:MM:SS' NumberFormatID = NumberFormat.queryKey(FormatString, LocalSettings, True) # check whether a value was found for the requested format (-1 == no value) if NumberFormatID == -1: NumberFormatID = NumberFormat.addNew(FormatString, LocalSettings) cell.NumberFormat = NumberFormatID else: print('Unsupported type: {}'.format(type(data))) # return data without conversion to trigger an exception return data
def loadHunspell(self): # Hunspell is a fallback spellchecker try: self.xHunspell = self.xSvMgr.createInstance( "org.openoffice.lingu.MySpellSpellChecker") except: print("Hunspell: init failed") traceback.print_exc() self.xHunspell = False self.bHunspell = False else: self.xHunspellLocale = Locale('fr', 'MC', '') self.bHunspell = not bool( self.xOptionNode.getPropertyValue("use_graphspell_sugg"))
def __init__(self, ctx): sLocaleData = "com.sun.star.i18n.LocaleData" self.LocaleData = ctx.ServiceManager.createInstance(sLocaleData) sProvider = "com.sun.star.configuration.ConfigurationProvider" sAccess = "com.sun.star.configuration.ConfigurationAccess" aConfigProvider = ctx.ServiceManager.createInstance(sProvider) prop = uno.createUnoStruct('com.sun.star.beans.PropertyValue') prop.Name = "nodepath" prop.Value = "/org.openoffice.Setup/L10N" self.aSettings = aConfigProvider.createInstanceWithArguments(sAccess,(prop,)) self.uilocale = self.aSettings.getByName("ooLocale") self.locale = Locale("en", "US", "") self.func = ctx.ServiceManager.createInstance('com.sun.star.sheet.FunctionAccess') for i in locales: langname[i.split("_")[0]] = i
def __init__( self, ctx, *args ): self.ctx = ctx self.ServiceName = "com.sun.star.linguistic2.Proofreader" self.ImplementationName = "org.openoffice.comp.pyuno.Lightproof." + pkg self.SupportedServiceNames = (self.ServiceName, ) self.locales = [] for i in locales: l = locales[i] self.locales += [Locale(l[0], l[1], l[2])] self.locales = tuple(self.locales) currentContext = uno.getComponentContext() lightproof_impl_${implname}.SMGR = currentContext.ServiceManager lightproof_impl_${implname}.spellchecker = \ lightproof_impl_${implname}.SMGR.createInstanceWithContext("com.sun.star.linguistic2.SpellChecker", currentContext) lightproof_handler_${implname}.load(currentContext)
def __containsLocale(self, localeToFind, locales): for locale in locales: if locale.Language == localeToFind.Language and locale.Country == localeToFind.Country: return True if locale.Language == "qlt" and \ (locale.Variant == localeToFind.Language or (localeToFind.Language == "qlt" and locale.Variant == localeToFind.Variant)): return True if localeToFind.Language == "qlt": # See if we can try again with a trimmed tag: some tags may contain extra # components that can be skipped while matching such as country in crk-Cans-CN tagToFind = localeToFind.Variant tagLen = len(tagToFind) if tagLen > 9 and tagToFind[tagLen - 3] == "-": loc = Locale("qlt", "", tagToFind[0:-3]) return self.__containsLocale(loc, locales) return False
def test_tdf46852(self): supported_locale = self.is_supported_locale("en", "US") if not supported_locale: self.skipTest("no dictionary support for en_US available") # This automates the steps described in the bug report tdf#46852 # Step 1: Create a document with repetitious misspelled words self.ui_test.create_doc_in_start_center("writer") document = self.ui_test.get_component() cursor = document.getCurrentController().getViewCursor() # Inserted text must be en_US, so make sure to set language in current location cursor.CharLocale = Locale("en", "US", "") input_text = self.TDF46852_INPUT.replace('\n', '\r') # \r = para break document.Text.insertString(cursor, input_text, False) # Step 2: Place cursor on 4th line after second "frogg" cursor.goUp(2, False) cursor.goLeft(1, False) # Step 3: Initiate spellchecking, and make sure "Check grammar" is # unchecked spell_dialog = self.launch_dialog() checkgrammar = spell_dialog.getChild('checkgrammar') if get_state_as_dict(checkgrammar)['Selected'] == 'true': checkgrammar.executeAction('CLICK', ()) self.assertTrue(get_state_as_dict(checkgrammar)['Selected'] == 'false') # Step 4: Repetitively click on "Correct all" for each misspelling # prompt until end of document is reached. changeall = spell_dialog.getChild('changeall') changeall.executeAction("CLICK", ()) changeall.executeAction("CLICK", ()) # The third time we click on changeall, the click action is going to # block while two message boxes are shown, so we need to do this third # click specially: self.ui_test.execute_blocking_action( changeall.executeAction, args=('CLICK', ()), # Step 5: Confirm to "Continue check at beginning of document" dialog_handler=lambda dialog : self.ui_test.execute_blocking_action( dialog.getChild('yes').executeAction, 'ok', ('CLICK', ()) ) ) output_text = document.Text.getString().replace('\r\n', '\n') self.assertTrue(re.match(self.TDF46852_REGEX, output_text))
def treatmentTable(doc, text, cursor, items, treatments, price, dates, patient, modifier=None): table, unitCount = createTable(doc, text, cursor, len(treatments)) if not modifier: modifier = [] for x in range(len(treatments)): modifier.append('') for a, b, c, d, e in zip(enumerate(treatments), dates, items, price, modifier): if e == '14' or e == '13' or e == '10': insertTextIntoCell(table, "A" + str(a[0] + 2), str(c.zfill(3) + " (0" + e + ")")) elif e == '6' or e == '8' or e == '9': insertTextIntoCell(table, "A" + str(a[0] + 2), str(c.zfill(3) + " (00" + e + ")")) elif ('namaf_orthopaedic_surgeons' in patient['tariff']): insertTextIntoCell(table, "A" + str(a[0] + 2), c.zfill(4)) else: insertTextIntoCell(table, "A" + str(a[0] + 2), c.zfill(3)) units_float = float(a[1]['units']) / 100 insertTextIntoCell(table, "D" + str(a[0] + 2), b) insertTextIntoCell(table, "B" + str(a[0] + 2), a[1]['description']) insertTextIntoCell(table, "C" + str(a[0] + 2), units_float) insertTextIntoCell(table, "E" + str(a[0] + 2), d) cell_sum = table.getCellByName("E" + str(2 + unitCount)) cell_sum.setFormula("=sum <E2:E" + str(1 + unitCount) + ">") cRange = table.getCellRangeByName("E2:E" + str(2 + unitCount)) xNumberFormats = doc.NumberFormats xLocale = Locale('en', 'US', '') format_string = '#,##0.00#' #[$€-407];[RED]-#,##0.00 [$€-407]' key = xNumberFormats.queryKey(format_string, xLocale, True) key = xNumberFormats.addNew(format_string, xLocale) cRange.NumberFormat = key cRange.setPropertyValue("ParaAdjust", RIGHT) # NumForms = doc.getNumberFormats() # dateFormatString = "YYYY/MM/DD\\ HH:MM:SS" # DateKey = NumForms.queryKey(dateFormatString, sLocale, True) # cell_sum.NumberFormat = DateKey return doc, text
def test_tdf32082(self): xDoc = CheckTable._uno.openEmptyWriterDoc() xDocFrame = xDoc.CurrentController.Frame xContext = CheckTable._uno.getContext() xServiceManager = xContext.ServiceManager xDispatcher = xServiceManager.createInstanceWithContext( 'com.sun.star.frame.DispatchHelper', xContext) xTable = xDoc.createInstance("com.sun.star.text.TextTable") xTable.initialize(1, 1) xCursor = xDoc.Text.createTextCursor() xDoc.Text.insertTextContent(xCursor, xTable, False) # Setup numberformat for the cell xNumberFormats = xDoc.NumberFormats xLocale = Locale('en', 'US', '') format_string = '#,##0.00 [$€-407];[RED]-#,##0.00 [$€-407]' key = xNumberFormats.queryKey(format_string, xLocale, True) if key == -1: key = xNumberFormats.addNew(format_string, xLocale) # Apply the format on the first cell xTable[0, 0].NumberFormat = key xDispatcher.executeDispatch(xDocFrame, '.uno:GoToStartOfDoc', '', 0, ()) xDispatcher.executeDispatch(xDocFrame, '.uno:InsertText', '', 0, (PropertyValue('Text', 0, '3', 0), )) xDispatcher.executeDispatch(xDocFrame, '.uno:JumpToNextCell', '', 0, ()) # Check that the formatting we set up is not destroyed self.assertEqual(xTable[0, 0].getString(), '3.00 €') self.assertEqual(xTable[0, 0].getValue(), 3) # Verify that it works with number recognition turned on as well xDispatcher.executeDispatch( xDocFrame, '.uno:TableNumberRecognition', '', 0, (PropertyValue('TableNumberRecognition', 0, True, 0), )) xDispatcher.executeDispatch(xDocFrame, '.uno:InsertText', '', 0, (PropertyValue('Text', 0, '4', 0), )) xDispatcher.executeDispatch(xDocFrame, '.uno:JumpToNextCell', '', 0, ()) self.assertEqual(xTable[1, 0].getString(), '4.00 €') self.assertEqual(xTable[1, 0].getValue(), 4) xDoc.dispose()
def __init__ (self, ctx, *args): self.ctx = ctx self.ServiceName = "com.sun.star.linguistic2.Proofreader" self.ImplementationName = "org.openoffice.comp.pyuno.Lightproof." + gce.pkg self.SupportedServiceNames = (self.ServiceName, ) self.locales = [] for i in gce.locales: l = gce.locales[i] self.locales.append(Locale(l[0], l[1], l[2])) self.locales = tuple(self.locales) xCurCtx = uno.getComponentContext() # init gce.load() # GC options # opt_handler.load(xCurCtx) dOpt = Options.load(xCurCtx) gce.setOptions(dOpt) # store for results of big paragraphs self.dResult = {} self.nMaxRes = 1500 self.lLastRes = deque(maxlen=self.nMaxRes) self.nRes = 0
def __init__( self, ctx ): self.ctx = ctx self.locale = Locale("en","EN", "" )
def translateodt(worksheet: str, languagecode: str) -> Optional[str]: """ Central function to process the given worksheet @param worksheet name of the worksheet (e.g. "Forgiving_Step_by_Step") @param languagecode what language we should translate to (e.g. "de") @return file name of the created odt file (or None in case of error) """ translations = fortraininglib.get_translation_units(worksheet, languagecode) if isinstance(translations, str): # This means we couldn't get the translation units so we can't do anything logger.error(translations) return None # Check for templates we need to read as well templates = set(fortraininglib.list_page_templates(worksheet)) \ - set(IGNORE_TEMPLATES) for template in templates: response = fortraininglib.get_translation_units(template, languagecode) if isinstance(response, str): logger.warning(f"Couldn't get translations of {template}, ignoring this template.") else: translations.extend(response) # find out version, name of original odt-file and name of translated odt-file version = None version_orig = None odt = None filename = None for t in translations: if re.search(r"\.odt", t["definition"]): odt = t["definition"] filename = t["translation"] # Searching for version number (valid examples: 1.0; 2.1; 0.7b; 1.5a) if re.search(r"^\d\.\d[a-zA-Z]?$", t["definition"]): if t["translation"] != t["definition"]: logger.warning(f"English original has version {t['definition']}, " f"translation has version {t['translation']}. " "Please update translation. " "Ask an administrator for a list of changes in the English original.") version = t["translation"] version_orig = t["definition"] if not odt: logger.error(f"Couldn't find name of odt file in page {worksheet}") return None if not version_orig: logger.error(f"Couldn't find version number in page {worksheet}") return None if not version: logger.warning("Translation of version is missing!") version = version_orig if not filename: logger.warning("Translation of file name is missing!") # add footer (Template:CC0Notice) to translation list translations.extend([{ "definition": fortraininglib.get_cc0_notice(version_orig, 'en'), "translation": fortraininglib.get_cc0_notice(version, languagecode)}]) en_path = config['Paths']['worksheets'] + 'en' if not os.path.isdir(en_path): os.makedirs(en_path) odt_path = en_path + '/' + odt if os.path.isfile(odt_path): logger.warning(f"File {odt_path} already exists locally, not downloading.") else: url = fortraininglib.get_file_url(odt) if url is None: logger.error(f"Could not get URL of file {odt}") return None odt_doc = requests.get(url, allow_redirects=True) with open(odt_path, 'wb') as fh: fh.write(odt_doc.content) logger.info(f"Successfully downloaded and saved {odt_path}") #sleep(30) ############################################################################################ # Open and Translate odt ############################################################################################ # open document and replace through translations oo_data = open_doc(odt_path) # for each translation unit: for t in translations: orig = t["definition"] trans = t["translation"] if not isinstance(orig, str): logger.warning("Empty unit in original detected") continue if not isinstance(trans, str): logger.warning(f"Translation missing. Please translate the following part: {orig}") continue if orig == version_orig: # We don't try to do search and replace with the version string. We later process the whole CC0 notice continue logger.debug(f"Translation unit: {orig}") # Check if number of <br/> is equal, otherwise replace by newline br_in_orig = len(re.split("< *br */ *>", orig)) br_in_trans = len(re.split("< *br */ *>", trans)) if br_in_orig != br_in_trans: orig = re.sub("< *br */ *>", '\n', orig) trans = re.sub("< *br */ *>", '\n', trans) orig_split = split_translation_unit(orig) trans_split = split_translation_unit(trans) # check if the structure of the original and the translation fit together if len(orig_split) != len(trans_split): # TODO give more specific warnings like "missing #" or "Number of = mismatch" logger.info('''Number of '*','=', '#', italic and bold formatting, ';', ':' and html tags is not equal in original and translation:''' + '\n' + t["definition"] + '\n\n' + t["translation"] + '\n\n\n') # fall back: removing all formatting and trying it this way logger.info('Falling back: removing all formatting, trying this now') orig_split = split_translation_unit(orig, True) trans_split = split_translation_unit(trans, True) if len(orig_split) != len(trans_split): if br_in_orig != br_in_trans: # There could be another issue besides the <br/> issue. Still this warning is probably helpful logger.warning(f"Couldn't process the following translation unit. Reason: Missing/wrong <br/>. " f"In original: {br_in_orig}, in translation: {br_in_trans}. Please correct.") else: logger.warning("Couldn't process the following translation unit. Reason: Formatting issues. " "Please check that all special characters like * = # ; : <b> <i> are correct.") logger.warning(f"Original: \n{t['definition']}") logger.warning(f"Translation: \n{t['translation']}") continue logger.warning("Found an issue with formatting (special characters like * = # ; : <b> <i>). " "I'm removing all formatting and continuing. You may ignore this error " f"or correct the translation unit {t['title']}") if br_in_orig != br_in_trans: logger.warning(f"Issue with <br/> (line breaks). There are {br_in_orig} in the original " f"but {br_in_trans} of them in the translation. " f"We still can process {t['title']}. You may ignore this warning.") # for each snippet of translation unit: for i in range(len(orig_split)): process_snippet(oo_data, orig_split[i], trans_split[i]) ############################################################################################ # Set properties ############################################################################################ desktop, model, proc = oo_data docProps = model.getDocumentProperties() # check if there is a subtitle in docProps.Subject: subtitle_en = "" subtitle_lan = "" if docProps.Subject != "": if docProps.Subject != translations[1]['definition']: logger.info(f"Assuming we have no subtitle. Subject in properties is {docProps.Subject}" f", but second translation unit is {translations[1]['definition']}") else: subtitle_en = " - " + translations[1]['definition'] subtitle_lan = " - " + translations[1]['translation'] # Title: [translated Title] headline = translations[0]['translation'] if headline is None: logger.error("Headline doesn't seem to be translated. Exiting now.") return None docProps.Title = headline docProps.Title += subtitle_lan # Subject: [English title] [Languagename in English] [Languagename autonym] docProps.Subject = str(translations[0]['definition']) docProps.Subject += subtitle_en docProps.Subject += " " + str(fortraininglib.get_language_name(languagecode, 'en')) docProps.Subject += " " + str(fortraininglib.get_language_name(languagecode)) # Keywords: [Translated copyright notice with replaced version number] - copyright-free, version [versionnumber] # ",version [versionnumber]" is omitted in languages where the translation of "version" is very similar cc0_notice = fortraininglib.get_cc0_notice(version, languagecode) + " - copyright-free" if languagecode not in NO_ADD_ENGLISH_VERSION: if re.search(r"^[0-9]\.[0-9][a-zA-Z]?$", version): cc0_notice += ", version " + version else: cc0_notice += ", version " + version_orig logger.warning("Version number seems not to use standard decimal numbers." f"Assuming this is identical to {version_orig}. Please check File->Properties->Keywords") docProps.Keywords = [cc0_notice] # create filename from headline filename_check = re.sub(" ", '_', headline) filename_check = re.sub("[':]", "", filename_check) filename_check += ".odt" if filename != filename_check: logger.warning("Warning: Is the file name not correctly translated? Please correct. " f"Translation: {filename}, according to the headline it should be: {filename_check}") filename = filename_check par_styles = model.getStyleFamilies().getByName("ParagraphStyles") default_style = None if par_styles.hasByName('Default Style'): # until LibreOffice 6 default_style = par_styles.getByName('Default Style') elif par_styles.hasByName('Default Paragraph Style'): # got renamed in LibreOffice 7, see https://bugs.documentfoundation.org/show_bug.cgi?id=129568 default_style = par_styles.getByName('Default Paragraph Style') else: logger.warning("Couldn't find Default Style in paragraph styles." "Can't set RTL and language locale, please do that manually.") if default_style is not None: if fortraininglib.get_language_direction(languagecode) == "rtl": logger.debug("Setting language direction to RTL") default_style.ParaAdjust = 1 #alignment # 0: left # 1: right # 2: justified # 3: center # change default_style.WritingMode = 1 #writing direction: # 0: left-to-right # 1: right-to-left # 2,3: nothing selected # 4: "use superordinate object settings" #default_style.CharLocale.Language and .Country seem to be read-only logger.debug("Setting language locale of Default Style") if languagecode in LANG_LOCALE: l = LANG_LOCALE[languagecode] struct_locale = Locale(l.languagecode, l.countrycode, '') logger.info(f"Assigning Locale for language '{languagecode}': {l}") if l.isStandard(): default_style.CharLocale = struct_locale if l.isAsian(): default_style.CharLocaleAsian = struct_locale if l.isComplex(): default_style.CharLocaleComplex = struct_locale if l.hasCustomFont(): logger.warning(F'Using font "{l.getCustomFont()}". Please make sure you have it installed.') default_style.CharFontName = l.getCustomFont() default_style.CharFontNameAsian = l.getCustomFont() default_style.CharFontNameComplex = l.getCustomFont() else: logger.warning(f"Language '{languagecode}' not in LANG_LOCALE. Please ask an administrator to fix this.") struct_locale = Locale(languagecode, "", "") # We don't know which of the three this language belongs to... so we assign it to all Fontstyles # (unfortunately e.g. 'ar' can be assigned to "Western Font" so try-and-error-assigning doesn't work) default_style.CharLocale = struct_locale default_style.CharLocaleAsian = struct_locale default_style.CharLocaleComplex = struct_locale # save in folder worksheets/[languagecode]/ as odt and pdf, close open office save_path = config['Paths']['worksheets'] + languagecode if not os.path.isdir(save_path): os.makedirs(save_path) file_path = save_path + '/' + filename oo_save_close(oo_data, file_path) if keep_english_file: logger.info(f"Keeping {odt_path}") else: logger.debug(f"Removing {odt_path}") os.remove(odt_path) return file_path