Skip to content

Commit f793715

Browse files
committed
Cope pasted code from Browser library
1 parent 2d7c01f commit f793715

1 file changed

Lines changed: 68 additions & 2 deletions

File tree

src/SeleniumLibrary/__init__.py

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@
1515
# limitations under the License.
1616
from collections import namedtuple
1717
from datetime import timedelta
18+
import importlib
1819
from inspect import getdoc, isclass
19-
from typing import Optional, List
20+
from pathlib import Path
21+
from typing import Optional, List, Union
2022

2123
from robot.api import logger
2224
from robot.errors import DataError
@@ -544,6 +546,46 @@ class SeleniumLibrary(DynamicCore):
544546
documentation for further details.
545547
546548
Plugin API is new SeleniumLibrary 4.0
549+
550+
= Language =
551+
552+
SeleniumLibrary offers possibility to translte keyword names and documentation to new language. If language
553+
is defined, SeleniumLibrary will search from
554+
[https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#module-search-path | module search path]
555+
Python packages starting with `robotframework_seleniumlibrary_translation` by using
556+
[https://packaging.python.org/en/latest/guides/creating-and-discovering-plugins/ | Python pluging API]. Library
557+
is using naming convention to find Python plugins.
558+
559+
The package must implement single API call, ``get_language`` without any arguments. Method must return a
560+
dictionary containing two keys: ``language`` and ``path``. The language key value defines which language
561+
the package contains. Also value should match (case insentive) the library ``language`` import parameter.
562+
The path parameter value should be full path to the translation file.
563+
564+
== Translation file ==
565+
566+
The file name or extension is not important, but data must be in [https://www.json.org/json-en.html | json]
567+
format. The keys of json are the methods names, not the keyword names, which implements keywords. Value of
568+
key is json object which contains two keys: ``name`` and ``doc``. The ``name`` key contains the keyword
569+
translated name and `doc` contains translated documentation. Providing doc and name are optional, example
570+
translation json file can only provide translations to keyword names or only to documentatin. But it is
571+
always recomended to provide translation to both name and doc. Special key ``__intro__`` is for class level
572+
documentation and ``__init__`` is for init level documentation. These special values ``name`` can not be
573+
translated, instead ``name`` should be kept the same.
574+
575+
== Generating template translation file ==
576+
577+
Template translation file, with English language can be created by running:
578+
`rfselib translation /path/to/translation.json` command. Command does not provide translations to other
579+
languages, it only provides easy way to create full list keywords and their documentation in correct
580+
format. It is also possible to add keywords from library plugins by providing `--plugings` arguments
581+
to command. Example: `rfselib translation --plugings myplugin.SomePlugin /path/to/translation.json` The
582+
genered json file contains `sha256` key, which constains the sha256 sum of the library documentation,
583+
the sha256 sum is used by `rfselib translation --compare /path/to/translation.json` command, which compares
584+
transation to to library and prints outs a table which tell if there are changes needed for translation file.
585+
586+
Example project for translation can be found from
587+
[https://github.com/MarketSquare/robotframework-seleniumlibrary-translation-fi | robotframework-seleniumlibrary-translation-fi]
588+
repository.
547589
"""
548590

549591
ROBOT_LIBRARY_SCOPE = "GLOBAL"
@@ -559,6 +601,7 @@ def __init__(
559601
event_firing_webdriver: Optional[str] = None,
560602
page_load_timeout=timedelta(minutes=5),
561603
action_chain_delay=timedelta(seconds=0.25),
604+
language: Optional[str] = None,
562605
):
563606
"""SeleniumLibrary can be imported with several optional arguments.
564607
@@ -581,6 +624,8 @@ def __init__(
581624
Default value to wait for page load to complete until a timeout exception is raised.
582625
- ``action_chain_delay``:
583626
Default value for `ActionChains` delay to wait in between actions.
627+
- ``language``:
628+
Defines language which is used to translate keyword names and documentation.
584629
"""
585630
self.timeout = _convert_timeout(timeout)
586631
self.implicit_wait = _convert_timeout(implicit_wait)
@@ -622,7 +667,8 @@ def __init__(
622667
self._plugins = plugin_libs
623668
libraries = libraries + plugin_libs
624669
self._drivers = WebDriverCache()
625-
DynamicCore.__init__(self, libraries)
670+
translation_file = self._get_translation(language)
671+
DynamicCore.__init__(self, libraries, translation_file)
626672

627673
def run_keyword(self, name: str, args: tuple, kwargs: dict):
628674
try:
@@ -798,3 +844,23 @@ def _resolve_screenshot_root_directory(self):
798844
if is_string(screenshot_root_directory):
799845
if screenshot_root_directory.upper() == EMBED:
800846
self.screenshot_root_directory = EMBED
847+
848+
@staticmethod
849+
def _get_translation(language: Union[str, None]) -> Union[Path, None]:
850+
if not language:
851+
return None
852+
discovered_plugins = {
853+
name: importlib.import_module(name)
854+
for _, name, _ in pkgutil.iter_modules()
855+
if name.startswith("robotframework_seleniumlibrary_translation")
856+
}
857+
for plugin in discovered_plugins.values():
858+
try:
859+
data = plugin.get_language()
860+
except AttributeError:
861+
continue
862+
if data.get("language", "").lower() == language.lower() and data.get(
863+
"path"
864+
):
865+
return Path(data.get("path")).absolute()
866+
return None

0 commit comments

Comments
 (0)