def test_lang_code(self): component = Component() component.filemask = 'Solution/Project/Resources.*.resx' self.assertEqual( component.get_lang_code('Solution/Project/Resources.es-mx.resx'), 'es-mx' ) self.assertEqual( component.get_lang_code('Solution/Project/Resources.resx'), '' ) self.assertRaisesMessage( ValidationError, 'Got empty language code for ' 'Solution/Project/Resources.resx, please check filemask!', component.clean_lang_codes, [ 'Solution/Project/Resources.resx', 'Solution/Project/Resources.de.resx', 'Solution/Project/Resources.es.resx', 'Solution/Project/Resources.es-mx.resx', 'Solution/Project/Resources.fr.resx', 'Solution/Project/Resources.fr-fr.resx', ] )
def test_lang_code_template(self): component = Component(project=Project()) component.filemask = 'Solution/Project/Resources.*.resx' component.template = 'Solution/Project/Resources.resx' self.assertEqual( component.get_lang_code('Solution/Project/Resources.resx'), 'en' )
def test_lang_code_double(self): component = Component() component.filemask = 'path/*/resources/MessagesBundle_*.properties' self.assertEqual( component.get_lang_code( 'path/pt/resources/MessagesBundle_pt_BR.properties' ), 'pt_BR' ) self.assertEqual( component.get_lang_code( 'path/el/resources/MessagesBundle_el.properties' ), 'el' )
def form_valid(self, form): if self.stage != 'init': return super(CreateFromZip, self).form_valid(form) # Create fake component (needed to calculate path) fake = Component( project=form.cleaned_data['project'], slug=form.cleaned_data['slug'], name=form.cleaned_data['name'], ) # Create repository try: LocalRepository.from_zip(fake.full_path, form.cleaned_data['zipfile']) except BadZipfile: form.add_error('zipfile', _('Failed to parse uploaded ZIP file.')) return self.form_invalid(form) # Move to discover phase self.stage = 'discover' self.initial = form.cleaned_data self.initial['vcs'] = 'local' self.initial['repo'] = 'local:' self.initial.pop('zipfile') self.request.method = 'GET' return self.get(self, self.request)
def validate_render_component(value, translation=None, **kwargs): from weblate.trans.models import Project, Component, Translation from weblate.lang.models import Language component = Component( project=Project( name='project', slug='project', id=-1, ), name='component', slug='component', branch='master', vcs='git', id=-1, ) if translation: kwargs['translation'] = Translation( id=-1, component=component, language_code='xx', language=Language(name='xxx', code='xx'), ) else: kwargs['component'] = component validate_render(value, **kwargs)
def check_unit(self, nplurals=3, template=None, source_info=None, **kwargs): if nplurals == 3: formula = "n==0 ? 0 : n==1 ? 1 : 2" else: formula = "0" lang = Language.objects.create(code="zz") plural = Plural.objects.create(language=lang, number=nplurals, formula=formula) project = Project(slug="test", source_language=Language.objects.get(code="en")) component = Component( slug="comp", project=project, file_format="xliff", template=template ) translation = Translation(language=lang, component=component, plural=plural) # Fake file format to avoid need for actual files translation.store = EmptyFormat(BytesIOMode("", b"")) unit = Unit(translation=translation, id_hash=-1, **kwargs) if source_info: for key, value in source_info.items(): setattr(unit, key, value) unit.__dict__["all_comments"] = [ Comment(comment="Weblate translator comment") ] unit.__dict__["suggestions"] = [ Suggestion(target="Weblate translator suggestion") ] else: unit.__dict__["all_comments"] = [] exporter = self.get_exporter(lang, translation=translation) exporter.add_unit(unit) return self.check_export(exporter)
def check_unit(self, nplurals=3, **kwargs): if nplurals == 3: equation = 'n==0 ? 0 : n==1 ? 1 : 2' else: equation = '0' lang = Language.objects.create( code='zz', ) plural = Plural.objects.create( language=lang, number=nplurals, equation=equation ) project = Project( slug='test', source_language=Language.objects.get(code='en'), ) component = Component(slug='comp', project=project) unit = Unit( translation=Translation( language=lang, component=component, plural=plural, ), id_hash=-1, **kwargs ) exporter = self.get_exporter(lang) exporter.add_unit(unit) return self.check_export(exporter)
def form_valid(self, form): if self.stage != "init": return super().form_valid(form) # Create fake component (needed to calculate path) fake = Component( project=form.cleaned_data["project"], slug=form.cleaned_data["slug"], name=form.cleaned_data["name"], ) # Create repository try: LocalRepository.from_zip(fake.full_path, form.cleaned_data["zipfile"]) except BadZipfile: form.add_error("zipfile", _("Failed to parse uploaded ZIP file.")) return self.form_invalid(form) # Move to discover phase self.stage = "discover" self.initial = form.cleaned_data self.initial["vcs"] = "local" self.initial["repo"] = "local:" self.initial.pop("zipfile") self.request.method = "GET" return self.get(self, self.request)
def check_unit(self, nplurals=3, template=None, **kwargs): if nplurals == 3: equation = 'n==0 ? 0 : n==1 ? 1 : 2' else: equation = '0' lang = Language.objects.create( code='zz', ) plural = Plural.objects.create( language=lang, number=nplurals, equation=equation ) project = Project( slug='test', source_language=Language.objects.get(code='en'), ) component = Component( slug='comp', project=project, file_format='xliff', template=template ) translation = Translation( language=lang, component=component, plural=plural, ) # Fake file format to avoid need for actual files translation.store = EmptyFormat(BytesIOMode('', b'')) unit = Unit(translation=translation, id_hash=-1, **kwargs) exporter = self.get_exporter(lang, translation=translation) exporter.add_unit(unit) return self.check_export(exporter)
def form_valid(self, form): if self.stage != "init": return super().form_valid(form) # Create fake component (needed to calculate path) fake = Component( project=form.cleaned_data["project"], slug=form.cleaned_data["slug"], name=form.cleaned_data["name"], ) # Create repository uploaded = form.cleaned_data["docfile"] ext = os.path.splitext(os.path.basename(uploaded.name))[1] filename = "{}/{}{}".format( form.cleaned_data["slug"], form.cleaned_data["project"].source_language.code, ext, ) LocalRepository.from_files(fake.full_path, {filename: uploaded.read()}) # Move to discover phase self.stage = "discover" self.initial = form.cleaned_data self.initial["vcs"] = "local" self.initial["repo"] = "local:" self.initial.pop("docfile") self.request.method = "GET" return self.get(self, self.request)
def test_lang_code(self): project = Project(language_aliases="xx:cs") component = Component(project=project) component.filemask = "Solution/Project/Resources.*.resx" # Pure extraction self.assertEqual( component.get_lang_code("Solution/Project/Resources.es-mx.resx"), "es-mx") # No match self.assertEqual( component.get_lang_code("Solution/Project/Resources.resx"), "") # Language aliases self.assertEqual( component.get_lang_code("Solution/Project/Resources.xx.resx"), "xx") self.assertEqual(component.get_language_alias("xx"), "cs") self.assertRaisesMessage( ValidationError, "The language code for " "Solution/Project/Resources.resx" " was empty, please check the filemask.", component.clean_lang_codes, [ "Solution/Project/Resources.resx", "Solution/Project/Resources.de.resx", "Solution/Project/Resources.es.resx", "Solution/Project/Resources.es-mx.resx", "Solution/Project/Resources.fr.resx", "Solution/Project/Resources.fr-fr.resx", ], )
def clone_repo(self, path): return self._class.clone( self.format_local_path(getattr(self, '{0}_repo_path'.format(self._vcs))), path, component=Component( slug='test', name='Test', project=Project(name='Test', slug='test') ), )
def clone_repo(self, path): return self._class.clone( self.get_remote_repo_url(), path, self._remote_branch, component=Component(slug="test", name="Test", project=Project(name="Test", slug="test")), )
def clone_repo(self, path): return self._class.clone( self.format_local_path(getattr(self, "{0}_repo_path".format(self._vcs))), path, component=Component( slug="test", name="Test", project=Project(name="Test", slug="test") ), )
def check_manage_units(translation: Translation, component: Component) -> bool: # Check if adding is generally allowed if not component.manage_units or translation.is_readonly: return False source = translation.is_source template = component.has_template() # Add to source in monolingual and to translations in bilingual if (source and not template) or (not source and template): return False return True
def test_lang_code(self): component = Component() component.filemask = 'Solution/Project/Resources.*.resx' self.assertEqual( component.get_lang_code('Solution/Project/Resources.es-mx.resx'), 'es-mx') self.assertEqual( component.get_lang_code('Solution/Project/Resources.resx'), '') self.assertRaisesMessage( ValidationError, 'Got empty language code for ' 'Solution/Project/Resources.resx, please check filemask!', component.clean_lang_codes, [ 'Solution/Project/Resources.resx', 'Solution/Project/Resources.de.resx', 'Solution/Project/Resources.es.resx', 'Solution/Project/Resources.es-mx.resx', 'Solution/Project/Resources.fr.resx', 'Solution/Project/Resources.fr-fr.resx', ])
def check_manage_units(translation: Translation, component: Component) -> bool: source = translation.is_source template = component.has_template() # Add only to source in monolingual if not source and template: return False # Check if adding is generally allowed if not component.manage_units or (template and not component.edit_template): return False return True
def setUp(self): self.unit = Unit(translation=Translation( component=Component( project=Project(source_language=Language(), slug="p", name="p"), slug="c", name="c", ), language=Language(), )) self.profile = Profile()
def create_component_from_zip(data): # Create fake component (needed to calculate path) fake = Component( project=data["project"], slug=data["slug"], name=data["name"], ) # Create repository LocalRepository.from_zip(fake.full_path, data["zipfile"]) return fake
def handle(self, *args, **options): """List installed add-ons.""" fake_addon = Addon(component=Component(project=Project(pk=-1), pk=-1)) for _unused, obj in sorted(ADDONS.items()): self.stdout.write(f".. _addon-{obj.name}:") self.stdout.write("\n") self.stdout.write(obj.verbose) self.stdout.write("-" * len(obj.verbose)) self.stdout.write("\n") self.stdout.write(f":Add-on ID: ``{obj.name}``") if obj.settings_form: form = obj(fake_addon).get_settings_form(None) table = [(f"``{name}``", str(field.label), self.get_help_text(field, name)) for name, field in form.fields.items()] prefix = ":Configuration: " name_width = max( len(name) for name, _label, _help_text in table) label_width = max( len(label) for _name, label, _help_text in table) help_text_width = max( max(len(line) for line in help_text) if help_text else 0 for _name, _label, help_text in table) name_row = "-" * (name_width + 2) label_row = "-" * (label_width + 2) help_text_row = "-" * (help_text_width + 2) for name, label, help_text in table: if not prefix.isspace(): self.stdout.write( f"{prefix}+{name_row}+{label_row}+{help_text_row}+" ) prefix = " " if not help_text: line = "" self.stdout.write( f"{prefix}| {name:<{name_width}s} | {label:<{label_width}s} | {line:<{help_text_width}s} |" ) for pos, line in enumerate(help_text): if pos > 0: name = label = "" self.stdout.write( f"{prefix}| {name:<{name_width}s} | {label:<{label_width}s} | {line:<{help_text_width}s} |" ) self.stdout.write( f"{prefix}+{name_row}+{label_row}+{help_text_row}+") else: self.stdout.write( ":Configuration: `This add-on has no configuration.`") events = ", ".join(EVENT_NAMES[event] for event in obj.events) self.stdout.write(f":Triggers: {events}") self.stdout.write("\n") self.stdout.write("\n".join(wrap(obj.description, 79))) self.stdout.write("\n")
def test_lang_code(self): component = Component() component.filemask = "Solution/Project/Resources.*.resx" self.assertEqual( component.get_lang_code("Solution/Project/Resources.es-mx.resx"), "es-mx" ) self.assertEqual(component.get_lang_code("Solution/Project/Resources.resx"), "") self.assertRaisesMessage( ValidationError, "The language code for " "Solution/Project/Resources.resx" " was empty, please check the filemask.", component.clean_lang_codes, [ "Solution/Project/Resources.resx", "Solution/Project/Resources.de.resx", "Solution/Project/Resources.es.resx", "Solution/Project/Resources.es-mx.resx", "Solution/Project/Resources.fr.resx", "Solution/Project/Resources.fr-fr.resx", ], )
def test_description(self): unit = Unit( source="string", target="I have two two lemons lemons", translation=Translation( language=Language("cs"), component=Component(source_language=Language("en")), ), ) check = Check(unit=unit) self.assertEqual( self.check.get_description(check), "Text contains the same word twice in a row: lemons, two", )
def handle(self, *args, **options): """List installed add-ons.""" fake_addon = Addon(component=Component(project=Project())) for _unused, obj in sorted(ADDONS.items()): self.stdout.write(f".. _addon-{obj.name}:") self.stdout.write("\n") self.stdout.write(obj.verbose) self.stdout.write("-" * len(obj.verbose)) self.stdout.write("\n") if obj.settings_form: form = obj(fake_addon).get_settings_form(None) params = ", ".join(f"``{key}``" for key in form.fields.keys()) else: params = "`This add-on has no configuration.`" self.stdout.write(PARAMS_TABLE.format(obj.name, params)) self.stdout.write("\n") self.stdout.write("\n".join(wrap(obj.description, 79))) self.stdout.write("\n")
def test_description(self): unit = Unit( source="{0}''s brush is {1} centimeters tall", target="{0}'s brush is {1} centimeters tall", extra_flags="java-messageformat", translation=Translation( component=Component( file_format="auto", source_language=Language("en"), ), language=Language("cs"), ), ) check = Check(unit=unit) self.assertEqual( self.check.get_description(check), "You need to pair up an apostrophe with another one.", )
def scratch_create_component(project, name, slug, file_format): format_cls = FILE_FORMATS[file_format] template = '{}.{}'.format(project.source_language.code, format_cls.extension()) fake = Component(project=project, slug=slug, name=name) # Create VCS with empty file LocalRepository.from_files(fake.full_path, {template: format_cls.new_translation}) # Create component return Component.objects.create( file_format=file_format, filemask='*.{}'.format(format_cls.extension()), template=template, vcs='local', repo='local:', project=project, name=name, slug=slug, )
def create_component_from_doc(data): # Calculate filename uploaded = data["docfile"] ext = os.path.splitext(os.path.basename(uploaded.name))[1] filemask = "{}/{}{}".format(data["slug"], "*", ext) filename = filemask.replace( "*", data["source_language"].code if "source_language" in data else "en") # Create fake component (needed to calculate path) fake = Component( project=data["project"], slug=data["slug"], name=data["name"], template=filename, filemask=filemask, ) # Create repository LocalRepository.from_files(fake.full_path, {filename: uploaded.read()}) return fake
def check_unit(self, nplurals=3, template=None, source_info=None, **kwargs): if nplurals == 3: equation = 'n==0 ? 0 : n==1 ? 1 : 2' else: equation = '0' lang = Language.objects.create(code='zz', ) plural = Plural.objects.create(language=lang, number=nplurals, equation=equation) project = Project( slug='test', source_language=Language.objects.get(code='en'), ) component = Component(slug='comp', project=project, file_format='xliff', template=template) translation = Translation( language=lang, component=component, plural=plural, ) # Fake file format to avoid need for actual files translation.store = EmptyFormat(BytesIOMode('', b'')) unit = Unit(translation=translation, id_hash=-1, **kwargs) if source_info: for key, value in source_info.items(): setattr(unit, key, value) unit.get_comments = fake_get_comments unit.__dict__['suggestions'] = [ Suggestion(target='Weblate translator suggestion') ] else: unit.get_comments = empty_get_comments exporter = self.get_exporter(lang, translation=translation) exporter.add_unit(unit) return self.check_export(exporter)
def handle(self, *args, **options): """List installed add-ons.""" fake_addon = Addon(component=Component(project=Project())) for _unused, obj in sorted(ADDONS.items()): self.stdout.write(f".. _addon-{obj.name}:") self.stdout.write("\n") self.stdout.write(obj.verbose) self.stdout.write("-" * len(obj.verbose)) self.stdout.write("\n") self.stdout.write(f":Add-on ID: ``{obj.name}``") if obj.settings_form: form = obj(fake_addon).get_settings_form(None) table = [ (f"``{name}``", str(field.label), str(field.help_text)) for name, field in form.fields.items() ] prefix = ":Configuration: " name_width = max(len(row[0]) for row in table) label_width = max(len(row[1]) for row in table) help_text_width = max(len(row[2]) for row in table) name_row = "-" * (name_width + 2) label_row = "-" * (label_width + 2) help_text_row = "-" * (help_text_width + 2) for name, label, help_text in table: if not prefix.isspace(): self.stdout.write( f"{prefix}+{name_row}+{label_row}+{help_text_row}+" ) prefix = " " self.stdout.write( f"{prefix}| {name:<{name_width}s} | {label:<{label_width}s} | {help_text:<{help_text_width}s} |" ) self.stdout.write( f"{prefix}+{name_row}+{label_row}+{help_text_row}+" ) else: self.stdout.write(":Configuration: `This add-on has no configuration.`") self.stdout.write("\n") self.stdout.write("\n".join(wrap(obj.description, 79))) self.stdout.write("\n")
def create_component_from_doc(data): # Calculate filename uploaded = data["docfile"] guess_filemask_from_doc(data) filemask = data["filemask"] filename = filemask.replace( "*", data["source_language"].code if "source_language" in data else settings.DEFAULT_LANGUAGE, ) # Create fake component (needed to calculate path) fake = Component( project=data["project"], slug=data["slug"], name=data["name"], template=filename, filemask=filemask, ) # Create repository LocalRepository.from_files(fake.full_path, {filename: uploaded.read()}) return fake
def validate_render_component(value, translation=None, **kwargs): from weblate.lang.models import Language from weblate.trans.models import Component, Project, Translation component = Component( project=Project(name="project", slug="project", id=-1), name="component", slug="component", branch="main", vcs="git", id=-1, ) if translation: kwargs["translation"] = Translation( id=-1, component=component, language_code="xx", language=Language(name="xxx", code="xx"), ) else: kwargs["component"] = component validate_render(value, **kwargs)
def test_lang_code_template(self): component = Component(project=Project()) component.filemask = 'Solution/Project/Resources.*.resx' component.template = 'Solution/Project/Resources.resx' self.assertEqual( component.get_lang_code('Solution/Project/Resources.resx'), 'en')
def test_lang_code_template(self): component = Component(project=Project()) component.filemask = "Solution/Project/Resources.*.resx" component.template = "Solution/Project/Resources.resx" self.assertEqual( component.get_lang_code("Solution/Project/Resources.resx"), "en")
def handle(self, *args, **options): """Automatic import of components.""" # Get project try: project = Project.objects.get(slug=options['project']) except Project.DoesNotExist: raise CommandError('Project does not exist!') # Get main component main_component = None if options['main_component']: try: main_component = Component.objects.get( project=project, slug=options['main_component'] ) except Component.DoesNotExist: raise CommandError('Main component does not exist!') try: data = json.load(options['json-file']) except ValueError: raise CommandError('Failed to parse JSON file!') finally: options['json-file'].close() for item in data: if ('filemask' not in item or 'name' not in item): raise CommandError('Missing required fields in JSON!') if 'slug' not in item: item['slug'] = slugify(item['name']) if 'repo' not in item: if main_component is None: raise CommandError( 'No main component and no repository URL!' ) item['repo'] = main_component.get_repo_link_url() item['project'] = project try: component = Component.objects.get( slug=item['slug'], project=item['project'] ) self.stderr.write( 'Component {0} already exists'.format(component) ) if options['ignore']: continue if options['update']: for key in item: if key in ('project', 'slug'): continue setattr(component, key, item[key]) component.save() continue raise CommandError( 'Component already exists, use --ignore or --update!' ) except Component.DoesNotExist: component = Component(**item) try: component.full_clean() except ValidationError as error: for key, value in error.message_dict.items(): self.stderr.write( 'Error in {}: {}'.format(key, ', '.join(value)) ) raise CommandError('Component failed validation!') component.save(force_insert=True) self.stdout.write( 'Imported {0} with {1} translations'.format( component, component.translation_set.count() ) )
def handle(self, *args, **options): # noqa: C901 """Automatic import of components.""" # Get project try: project = Project.objects.get(slug=options['project']) except Project.DoesNotExist: raise CommandError('Project does not exist!') # Get main component main_component = None if options['main_component']: try: main_component = Component.objects.get( project=project, slug=options['main_component']) except Component.DoesNotExist: raise CommandError('Main component does not exist!') try: data = json.load(options['json-file']) except ValueError: raise CommandError('Failed to parse JSON file!') finally: options['json-file'].close() allfields = { field.name for field in Component._meta.get_fields() if field.editable and not field.is_relation } # Handle dumps from API if 'results' in data: data = data['results'] for item in data: if 'filemask' not in item or 'name' not in item: raise CommandError('Missing required fields in JSON!') if 'slug' not in item: item['slug'] = slugify(item['name']) if 'repo' not in item: if main_component is None: raise CommandError( 'No main component and no repository URL!') item['repo'] = main_component.get_repo_link_url() try: component = Component.objects.get(slug=item['slug'], project=project) self.stderr.write( 'Component {0} already exists'.format(component)) if options['ignore']: continue if options['update']: for key in item: if key not in allfields or key == 'slug': continue setattr(component, key, item[key]) component.save() continue raise CommandError( 'Component already exists, use --ignore or --update!') except Component.DoesNotExist: params = {key: item[key] for key in allfields if key in item} component = Component(project=project, **params) try: component.full_clean() except ValidationError as error: for key, value in error.message_dict.items(): self.stderr.write('Error in {}: {}'.format( key, ', '.join(value))) raise CommandError('Component failed validation!') component.save(force_insert=True) self.stdout.write('Imported {0} with {1} translations'.format( component, component.translation_set.count()))