Why are some items not translated in Odoo? - python

I have a problem with translations in Project module. Some menu items are not translated. What could be the problem?
Here project_view.xml
<!-- Top menu item -->
<menuitem name="Project"
id="base.menu_main_pm"
groups="group_project_manager,group_project_user"
icon="fa-calendar"
web_icon="project,static/description/icon.png"
sequence="50"/>
Here ru.po
#. module: project
#: model:ir.model,name:project.model_project_project
#: model:ir.model.fields,field_description:project.field_project_task_history_cumulative_project_id
#: model:ir.model.fields,field_description:project.field_project_task_project_id
#: model:ir.model.fields,field_description:project.field_report_project_task_user_project_id
#: model:ir.ui.view,arch_db:project.edit_project
#: model:ir.ui.view,arch_db:project.view_task_form2
#: model:ir.ui.view,arch_db:project.view_task_history_search
#: model:ir.ui.view,arch_db:project.view_task_project_user_search
#: model:ir.ui.view,arch_db:project.view_task_search_form
#: model:res.request.link,name:project.req_link_project
msgid "Project"
msgstr "Проект"

I've also had this problem with translations. I had updated module base a lot of times too and it worked, but sometimes it wasn't necessary. What I did is the next process:
Go to Settings > Translations > Load a Translation, select your
language and check the box Overwrite Existing Terms, then click on
Load button.
After that, press F5 to refresh the browser, then go to Settings >
Translations > Application Terms > Synchronize Terms, select your
language and click on Update. Then press again F5 to see if your
terms have been updated.
Regards.

Sometimes translations don't work very well. Try pressing the "Update" button in the "Base" module. This should solve the problem.
Update: 21 nov 2019
I do not know in older versions, but now there are more options in command line to update, import and export translations. The argument --i18n-overwrite might be useful in your case:
Use these options to translate Odoo to another language. See i18n
section of the user manual. Option '-d' is mandatory. Option '-l' is
mandatory in case of importation
--load-language=LOAD_LANGUAGE
specifies the languages for the translations you want
to be loaded
-l LANGUAGE, --language=LANGUAGE
specify the language of the translation file. Use it
with --i18n-export or --i18n-import
--i18n-export=TRANSLATE_OUT
export all sentences to be translated to a CSV file, a
PO file or a TGZ archive and exit
--i18n-import=TRANSLATE_IN
import a CSV or a PO file with translations and exit.
The '-l' option is required.
--i18n-overwrite overwrites existing translation terms on updating a
module or importing a CSV or a PO file.
--modules=TRANSLATE_MODULES
specify modules to export. Use in combination with
--i18n-export

Sometimes, is not enough to update the base module. I implemented a solution based on a post. What I do is clear the whole language using a query, and then reload the language again using. "Load a Translation" from config menu.
The query that made it possible, is the following, for example for es_CL:
DELETE FROM ir_translation WHERE lang = 'es_CL';
I've put this in a module, which you can use to adapt it to your needs:
https://github.com/odoo-chile/l10n_cl_clear_translation
When this module is instaled it runs the query. Then you can reload your language using the menu.

Yes, sometimes the localization doesn't work perfectly. Here's another strategy from v8, which may still help you in v9.
First, update your module like described
Then, remove all translated strings for your module from the database. This is safe, because you have them in your ru.po file.
Go to Settings > Translations > Application Terms > Translated Terms
Do an "Advanced Search" with 'Module' 'contains' to find all your terms
select them all (possibly set the pager to 'unlimited')
Select 'More' > 'Delete'
Confirm
Update your module again.
Export the ru.po file again; it should now contain all missing terms.
The issue seems to be that the module sometimes takes some values from the default (en) language into the target language, which then prohibits the term to be listed as 'to be translated'.

Related

Sphinx (for Python) - Search bar disappeared

I'm new to Sphinx and having completed my documentation I noticed the search bar has disappeared when it was there previously.
I haven't (knowingly) changed anything in the conf.py file and am not sure why this has happened.
Does anybody know how to get it back?
You need to include
* :ref:`modindex`
In the file which will named ./index.rst
From the docs ...
The special document names (and pages generated for them) are:
genindex, modindex, search
These are used for the general index, the Python module index, and the
search page, respectively.
The general index is populated with entries from modules, all
index-generating object descriptions, and from index directives.

Snippets vs. Abbreviations in Vim

What advantages and/or disadvantages are there to using a "snippets" plugin, e.g. snipmate, ultisnips, for VIM as opposed to simply using the builtin "abbreviations" functionality?
Are there specific use-cases where declaring iabbr, cabbr, etc. lack some major features that the snippets plugins provide? I've been unsuccessful in finding a thorough comparison between these two "features" and their respective implementations.
As #peter-rincker pointed out in a comment:
It should be noted that abbreviations can execute code as well. Often via <c-r>= or via an expression abbreviation (<expr>). Example which expands ## to the current file's path: :iabbrev ## <c-r>=expand('%:p')<cr>
As an example for python, let's compare a snipmate snippet and an abbrev in Vim for inserting lines for class declaration.
Snipmate
# New Class
snippet cl
class ${1:ClassName}(${2:object}):
"""${3:docstring for $1}"""
def __init__(self, ${4:arg}):
${5:super($1, self).__init__()}
self.$4 = $4
${6}
Vimscript
au FileType python :iabbr cl class ClassName(object):<CR><Tab>"""docstring for ClassName"""<CR>def __init__(self, arg):<CR><Tab>super(ClassName, self).__init__()<CR>self.arg = arg
Am I missing some fundamental functionality of "snippets" or am I correct in assuming they are overkill for the most part, when Vim's abbr and :help template templates are able to do all most of the stuff snippets do?
I assume it's easier to implement snippets, and they provide additional aesthetic/visual features. For instance, if I use abbr in Vim and other plugins for running/testing python code inside vim--e.g. syntastic, pytest, ropevim, pep8, etc--am I missing out on some key features that snippets provide?
Everything that can be done with snippets can be done with abbreviations and vice-versa. You can have (mirrored or not) placeholders with abbreviations, you can have context-sensitive snippets.
There are two important differences:
Abbreviations are triggered when the abbreviation text has been typed, and a non word character (or esc) is hit. Snippets are triggered on demand, and shortcuts are possible (no need to type while + tab. w + tab may be enough).
It's much more easier to define new snippets (or to maintain old ones) than to define abbreviations. With abbreviations, a lot of boiler plate code is required when we want to do neat things.
There are a few other differences. For instance, abbreviations are always triggered everywhere. And seeing for expanded into for(placeholder) {\n} within a comment or a string context is certainly not what the end-user expects. With snippets, this is not a problem any more: we can expect the end-user to know what's he's doing when he asks to expand a snippet. Still, we can propose context-aware snippets that expand throw into #throw {domain::exception} {explanation} within a comment, or into throw domain::exception({message}); elsewhere.
Snippets
Rough superset of Vim's native abbreviations. Here are the highlights:
Only trigger on key press
Uses placeholders which a user can jump between
Exist only for insert mode
Dynamic expansions
Abbreviations
Great for common typos and small snippets.
Native to Vim so no need for plugins
Typically expand on whitespace or <c-]>
Some special rules on trigger text (See :h abbreviations)
Can be used in command mode via :cabbrev (often used to create command aliases)
No placeholders
Dynamic expansions
Conclusion
For the most part snippets are more powerful and provide many features that other editors enjoy, but you can use both and many people do. Abbreviations enjoy the benefit of being native which can be useful for remote environments. Abbreviations also enjoy another clear advantage which is can be used in command mode.
Snippets are more powerful.
Depending on the implementation, snippets can let you change (or accept defaults for) multiple placeholders and can even execute code when the snippet is expanded.
For example with ultisnips, you can have it execute shell commands, vimscript but also Python code.
An (ultisnips) example:
snippet hdr "General file header" b
# file: `!v expand('%:t')`
# vim:fileencoding=utf-8:ft=`!v &filetype`
# ${1}
#
# Author: ${2:J. Doe} ${3:<jdoe#gmail.com>}
# Created: `!v strftime("%F %T %z")`
# Last modified: `!v strftime("%F %T %z")`
endsnippet
This presents you with three placeholders to fill in (it gives default values for two of them), and sets the filename, filetype and current date and time.
After the word "snippet", the start line contains three items;
the trigger string,
a description and
options for the snippet.
Personally I mostly use the b option where the snippet is expanded at the beginning of a line and the w option that expands the snippet if the trigger string starts at the beginning of a word.
Note that you have to type the trigger string and then input a key or key combination that actually triggers the expansion. So a snippet is not expanded unless you want it to.
Additionally, snippets can be specialized by filetype. Suppose you want to define four levels of headings, h1 .. h4. You can have the same name expand differently between e.g. an HTML, markdown, LaTeX or restructuredtext file.
snippets are like the built-in :abbreviate on steroids, usually with:
parameter insertions: You can insert (type or select) text fragments in various places inside the snippet. An abbreviation just expands once.
mirroring: Parameters may be repeated (maybe even in transformed fashion) elsewhere in the snippet, usually updated as you type.
multiple stops inside: You can jump from one point to another within the snippet, sometimes even recursively expand snippets within one.
There are three things to evaluate in a snippet plugin: First, the features of the snippet engine itself, second, the quality and breadth of snippets provided by the author or others; third, how easy it is to add new snippets.

How can I get a list of all the strings that Babel knows about?

I have an application in which the main strings are in English and then various translations are made in various .po/.mo files, as usual (using Flask and Flask-Babel). Is it possible to get a list of all the English strings somewhere within my Python code? Specifically, I'd like to have an admin interface on the website which lets someone log in and choose an arbitrary phrase to be used in a certain place without having to poke at actual Python code or .po/.mo files. This phrase might change over time but needs to be translated, so it needs to be something Babel knows about.
I do have access to the actual .pot file, so I could just parse that, but I was hoping for a cleaner method if possible.
You can use polib for this.
This section of the documentation shows examples of how to iterate over the contents of a .po file. Here is one taken from that page:
import polib
po = polib.pofile('path/to/catalog.po')
for entry in po:
print entry.msgid, entry.msgstr
If you alredy use babel you can get all items from po file:
from babel.messages.pofile import read_po
catalog = read_po(open(full_file_name))
for message in catalog:
print message.id, message.string
See http://babel.edgewall.org/browser/trunk/babel/messages/pofile.py.
You alredy can try get items from mo file:
from babel.messages.mofile import read_mo
catalog = read_po(open(full_file_name))
for message in catalog:
print message.id, message.string
But when I try use it last time it's not was availible. See http://babel.edgewall.org/browser/trunk/babel/messages/mofile.py.
You can use polib as #Miguel wrote.

Vim neocomplcache: disable usage prompt

I am using Vim with neocomplcache plugin, its feature of usage prompt while completion confused me so much.
It behaved like this: I typed <C-X><C-U> when the cursor was at the end of os.path., then not only completion candidates was listed under the line, but also a horizontal split
which contained docstring of the first candidate appeared
at the top. My question is: how to get rid of this feature so that I only get code completion without the usage prompt?
It's all because preview is in completeopt by default, you can see its value by type
command :set completeopt and the result should be completeopt=menu,preview.
What we need is just menu, so cut the preview, add this line in your vimrc:
set completeopt-=preview
vim help reference:
*'completeopt'* *'cot'*
'completeopt' 'cot' string (default: "menu,preview")
global
{not available when compiled without the
|+insert_expand| feature}
{not in Vi}
A comma separated list of options for Insert mode completion
|ins-completion|. The supported values are:
menu Use a popup menu to show the possible completions. The
menu is only shown when there is more than one match and
sufficient colors are available. |ins-completion-menu|
menuone Use the popup menu also when there is only one match.
Useful when there is additional information about the
match, e.g., what file it comes from.
longest Only insert the longest common text of the matches. If
the menu is displayed you can use CTRL-L to add more
characters. Whether case is ignored depends on the kind
of completion. For buffer text the 'ignorecase' option is
used.
preview Show extra information about the currently selected
completion in the preview window. Only works in
combination with "menu" or "menuone".

List available languages for PyGTK UI strings

I'm cleaning up some localisation and translation settings in our PyGTK application. The app is only intended to be used under GNU/Linux systems. One of the features we want is for users to select the language used for the applications (some prefer their native language, some prefer English for consistency, some like French because it sounds romantic, etc).
For this to work, I need to actually show a combo box with the various languages available. How can I get this list? In fact, I need a list of pairs of the language code ("en", "ru", etc) and the language name in the native language ("English (US)", "Русские").
If I had to implement a brute force method, I'd do something like: look in the system locale dir (eg. "/usr/share/locale") for all language code dirs (eg. "en/") containing the relative path "LC_MESSAGES/OurAppName.mo".
Is there a more programmatic way?
You can use gettext to find whether a translation is available and installed, but you need babel (which was available on my Ubuntu system as the package python-pybabel) to get the names. Here is a code snippet which returns the list that you want:
import gettext
import babel
messagefiles = gettext.find('OurAppName',
languages=babel.Locale('en').languages.keys(),
all=True)
messagefiles.sort()
languages = [path.split('/')[-3] for path in messagefiles]
langlist = zip(languages,
[babel.Locale.parse(lang).display_name for lang in languages])
print langlist
To change languages in the middle of your program, see the relevant section of the Python docs. This probably entails reconstructing all your GTK widgets, although I'm not sure.
For more information on gettext.find, here is the link to that too.
Here's a function inspired by gettext.find, but looks to see what files exist, rather than needing a list of languages from Babel. It returns the locale codes, you'll still have to use babel to get display_name for each.
def available_langs(self, domain=None, localedir=None):
if domain is None:
domain = gettext._current_domain
if localedir is None:
localedir = gettext._default_localedir
files = glob(os.path.join(localedir, '*', 'LC_MESSAGES', '%s.mo' % domain))
langs = [file.split(os.path.sep)[-3] for file in files]
return langs

Categories