PyGtk3 and Gettext - problem choosing the language at run-time - internationalization

Long story short, when I thought the strings would be translated, nothing happens.
I have a PyGtk application and a module where I store all the strings that I want to be translated in the following way:
'''
Strings module.
'''
....
CANCEL_BUTTON_TEXT = _("Cancel")
BACK_BUTTON_TEXT = _("Back")
....
And so on. So then they are used from other modules like:
'''
View module.
'''
import strings
# Usage example
button.set_label(strings.CANCEL_BUTTON_TEXT)
button.set_tooltip(strings.TOOLTIP)
window_title.set_title(strings.WINDOW_TITLE)
...
I have created the necessary .mo files. This is the jerarquy I have:
/locales
/es
LC_MESSAGES
base.mo
base.po
/en
LC_MESSAGES
base.mo
base.po
base.pot
As the documentation says (https://docs.python.org/3/library/gettext.html), in my main.py I have the following lines:
import gettext
gettext.install('myapplication')
es_lang = gettext.translation('base', localedir='locales', languages=['es'])
en_lang = gettext.translation('base', localedir='locales', languages=['en'])
es_lang.install()
Then, in my application I have a button, that when is pressed, the following line is executed:
en_lang.install()
But the spanish language is still used on the widgets. Could anyone help me out?

So, what I was doing wrong is I was translating the strings but I wasn't updating the GTK Widgets labels, among other things.
The way I solved this was:
i) Created a class where I put all the strings I want to translate when the user selects a language. That class is the only one to import the gettext module.
ii) When the user selects a language, a method of that class is called and it translates all strings to that language.
iii) Another method outside that class updates all labels and widgets that use those strings.

Related

Documenting class-level variables in Python

I am trying to document a Python class that has some class-level member variables, but I could not get it appropriately documented using reST/Sphinx.
The code is this:
class OSM:
"""Some blah and examples"""
url = 'http://overpass-api.de/api/interpreter' # URL of the Overpass API
sleep_time = 10 # pause between successive queries when assembling OSM dataset
But I get this output (see the green circled area, where I would like to have some text describing both variables, as above).
I apologize for the blurring, but part of the example is somewhat sensitive
You have several options to document class level variables.
Put a comment that starts with #: before the variable, or on the same line. (Uses only autodoc.)
Perhaps the easiest choice. If needed you can customize the value using :annotation: option. If you want to type-hint the value use #: type:.
Put a docstring after the variable.
Useful if the variable requires extensive documentation.
For module data members and class attributes, documentation can either be put into a comment with special formatting (using a #: to start the comment instead of just #), or in a docstring after the definition. Comments need to be either on a line of their own before the definition, or immediately after the assignment on the same line. The latter form is restricted to one line only.
Document the variable in the class docstring. (Uses sphinx-napoleon extension, shown in the example.)
This has the drawback that the variable's value will be omitted. Since it's a class level variable your IDE's static type checker may complain if you don't prefix the variable with cls. or class_name.. The distinction is however convenient because instance variables can also be documented in the class docstring.
The following example shows all three options. The .rst has additional complexity to illustrate the neededautodoc functionalities. Type hints were included in all cases but can also be omitted.
class OSM:
"""Some blah and examples"""
#: str: URL of the Overpass API.
url = 'http://overpass-api.de/api/interpreter'
#: int: pause between successive queries when assembling OSM dataset.
sleep_time = 10
class OSM2:
"""Some blah and examples.
Attributes:
cls.url (str): URL of the Overpass API.
"""
url = 'http://overpass-api.de/api/interpreter'
sleep_time = 10
"""str: Docstring of sleep_time after the variable."""
Corresponding .rst
OSM module
==========
.. automodule:: OSM_module
:members:
:exclude-members: OSM2
.. autoclass:: OSM2
:no-undoc-members:
:exclude-members: sleep_time
.. autoattribute:: sleep_time
:annotation: = "If you want to specify a different value from the source code."
The result:
This also works, if you're ok with suppressing a silly linter rule.
class OSM2:
sleep_time = 10; """str: Inline docstring of sleep_time after the variable."""

Sphinx nit-picky mode but only for links I explicitly wrote

I tried turning on Sphinx's nit-picky mode (-n) to catch any broken links I might have accidentally made. However, it spews out errors for all the places where I've documented types. In some cases I've described types semantically (e.g. "3D array"), but it does it even for types extracted from type hints (even with intersphinx set up to pull Python types). For example, for this module
from typing import Callable
def foo(x: Callable[..., int]):
pass
I get the error docstring of myproj.foo:: WARNING: py:class reference target not found: Callable[..., int]. That's with only sphinx.ext.autodoc and sphinx.ext.intersphinx extensions and a freshly-generated conf.py.
Is there some way to prevent Sphinx from trying to generate links for type information, or at least stop it complaining when they don't exist while still telling me about bad links in my hand-written documentation?
I'm using Sphinx 3.0.3.
Perhaps nitpick_ignore will do what you want? In your conf.py, something like this:
nitpick_ignore = [
("py:class", "Callable"),
]
I'm not sure of the exact values in the tuple that should be used, but I got the idea from this issue and a linked commit.
I had success solving a similar problem by writing a custom sphinx transform. I only wanted warnings for cross-references to my own package's python documentation. The following can be saved as a python file and added to extensions in conf.py once it is on the python path.
from sphinx import addnodes
from sphinx.errors import NoUri
from sphinx.transforms.post_transforms import SphinxPostTransform
from sphinx.util import logging
logger = logging.getLogger(__name__)
class MyLinkWarner(SphinxPostTransform):
"""
Warns about broken cross-reference links, but only for my_package_name.
This is very similar to the sphinx option ``nitpicky=True`` (see
:py:class:`sphinx.transforms.post_transforms.ReferencesResolver`), but there
is no way to restrict that option to a specific package.
"""
# this transform needs to happen before ReferencesResolver
default_priority = 5
def run(self):
for node in self.document.traverse(addnodes.pending_xref):
target = node["reftarget"]
if target.startswith("my_package_name."):
found_ref = False
with suppress(NoUri, KeyError):
# let the domain try to resolve the reference
found_ref = self.env.domains[node["refdomain"]].resolve_xref(
self.env,
node.get("refdoc", self.env.docname),
self.app.builder,
node["reftype"],
target,
node,
nodes.TextElement("", ""),
)
# warn if resolve_xref did not return or raised
if not found_ref:
logger.warning(
f"API link {target} is broken.", location=node, type="ref"
)
def setup(app):
app.add_post_transform(MyLinkWarner)

How to add link to source code in Sphinx

class torch.FloatStorage[source]
byte()
Casts this storage to byte type
char()
Casts this storage to char type
Im trying to get some documentation done, i have managed to to get the format like the one shown above, But im not sure how to give that link of source code which is at the end of that function!
The link takes the person to the file which contains the code,But im not sure how to do it,
This is achieved thanks to one of the builtin sphinx extension.
The one you are looking for in spinx.ext.viewcode. To enable it, add the string 'sphinx.ext.viewcode' to the list extensions in your conf.py file.
In summary, you should see something like that in conf.py
extensions = [
# other extensions that you might already use
# ...
'sphinx.ext.viewcode',
]
I'd recommend looking at the linkcode extension too. Allows you to build a full HTTP link to the code on GitHub or such like. This is sometimes a better option that including the code within the documentation itself. (E.g. may have stronger permission on it than the docs themselves.)
You write a little helper function in your conf.py file, and it does the rest.
What I really like about linkcode is that it creates links for enums, enum values, and data elements, which I could not get to be linked with viewcode.
I extended the link building code to use #:~:text= to cause the linked-to page to scroll to the text. Not perfect, as it will only scroll to the first instance, which may not always be correct, but likely 80~90% of the time it will be.
from urllib.parse import quote
def linkcode_resolve(domain, info):
# print(f"domain={domain}, info={info}")
if domain != 'py':
return None
if not info['module']:
return None
filename = quote(info['module'].replace('.', '/'))
if not filename.startswith("tests"):
filename = "src/" + filename
if "fullname" in info:
anchor = info["fullname"]
anchor = "#:~:text=" + quote(anchor.split(".")[-1])
else:
anchor = ""
# github
result = "https://<github>/<user>/<repo>/blob/master/%s.py%s" % (filename, anchor)
# print(result)
return result

Is it possible to replace one directive with another one

I would like to create a substitution (or similar) that transforms one directive into another.
For example:
In our sphinx based documentation, we use Admonitions to create certain note and warning boxes.
However, if we use
.. note:: This is a Note
The title of the box is Note, and This is a Note becomes the first paragraph.
In contrast, this directive
.. admonition:: This is a Note
:class: note
produces a note box with the desired title.
To make it easier for other editors, I would like to create a substitution, that replaces the first with the second.
Is there anything this can be done with in sphinx?
Yes, it can be done. You have to add a custom directive to Sphinx. Create a Python module (like mydirectives.py next to conf.py) with the following:
import os
import os.path
import re
import subprocess
import docutils.core
import docutils.nodes
import docutils.parsers.rst
class AbstractDirective(docutils.parsers.rst.Directive):
has_content = True
required_arguments = 0
optional_arguments = 0
option_spec = {}
final_argument_whitespace = False
node_class = docutils.nodes.container
def run(self):
self.assert_has_content()
text = '\n'.join(self.content)
admonition_node = self.node_class(rawsource=text)
self.state.nested_parse(self.content, self.content_offset,
admonition_node)
admonition_node.set_class("abstract")
return [admonition_node]
def setup(app):
app.add_directive('abstract', AbstractDirective)
There must be some way to add the title as well. Perhaps you need to add a
title node yourself. The documentation is lacking there, best look at the
source for
admonitions
and you will get a feel for the docutils.
With a custom text node you should be able to make up your own note directive.

How to print right-to-left report on odoo 8

I created a report in odoo 8 using RML, everything is good. but when i print the report, caracteres are printed from left to right. I tried with drawRightString but nothing does appears on the PDF.
I used openerp-rtl module but I noticed no changes.
What can i do to print it in RTL mode.
Generally people working on Right to left text on Arbic Language.
so in this case you just install the below python-bidi package :
https://pypi.python.org/pypi/python-bidi/
python-bidi package is helpful to set the Pure python implementation of the BiDi layout algorithm.
And also add the bidi directory in your OpenERP report dir and use the get_display(string) method for making your sting convert into the arbic formate and also use with the arabic_reshaper class
You can do some thing like
import arabic_reshaper
from bidi.algorithm import get_display
def get_arabic_string(string):
reshaped_text = arabic_reshaper.reshape(string)
bidi_text = get_display(reshaped_text)
return bidi_text
Just need to use the get_arbic_string function in your rml file and set it on rml and pass the sting as arbic formate.
just check another source :
pyfribidi for windows or any other bidi algorithm

Resources