diff --git a/weblate/trans/discovery.py b/weblate/trans/discovery.py index 6e8f734b76d5..bbe98fac9705 100644 --- a/weblate/trans/discovery.py +++ b/weblate/trans/discovery.py @@ -118,16 +118,21 @@ class DetectedDiscoveryPreset(TypedDict): def get_discovery_result_key( result: DiscoveryResult, -) -> tuple[str, str, str, str, str]: +) -> tuple[str, str, str, str, str, str]: return ( str(result.get("file_format", "")), str(result.get("filemask", "")), str(result.get("template", "")), str(result.get("new_base", "")), str(result.get("intermediate", "")), + get_discovery_language_regex(result), ) +def get_discovery_language_regex(result: DiscoveryResult) -> str: + return str(result.get("language_regex") or "^[^.]+$") + + def split_discovery_path(value: str) -> list[str]: return value.split("/") if value else [] @@ -296,6 +301,10 @@ def build_detected_discovery_preset( if first.get("file_format") != second.get("file_format"): return None + language_regex = get_discovery_language_regex(first) + if language_regex != get_discovery_language_regex(second): + return None + filemasks = [str(first.get("filemask", "")), str(second.get("filemask", ""))] if any(not filemask or filemask.count("*") != 1 for filemask in filemasks): return None @@ -370,7 +379,7 @@ def build_detected_discovery_preset( "match": match, "file_format": str(first["file_format"]), "name_template": DISCOVERY_PRESET_COMPONENT_TEMPLATE, - "language_regex": "^[^.]+$", + "language_regex": language_regex, "base_file_template": base_file_template, "new_base_template": new_base_template, "intermediate_template": intermediate_template, @@ -385,7 +394,7 @@ def build_detected_discovery_preset( def get_detected_discovery_presets_from_results( discovered: list[DiscoveryResult], ) -> list[DetectedDiscoveryPreset]: - unique_results: dict[tuple[str, str, str, str, str], DiscoveryResult] = {} + unique_results: dict[tuple[str, str, str, str, str, str], DiscoveryResult] = {} for result in discovered: key = get_discovery_result_key(result) if key[0] and key[1]: diff --git a/weblate/trans/tests/test_create.py b/weblate/trans/tests/test_create.py index ffa4bb803a62..f2b7c5b082b5 100644 --- a/weblate/trans/tests/test_create.py +++ b/weblate/trans/tests/test_create.py @@ -205,6 +205,7 @@ def test_create_component_wizard_discovery_file_format_params(self) -> None: "properties_encoding": "utf-8", "strings_encoding": "utf-16", }, + "language_regex": "^(?!en$).+$", }, ) ) @@ -244,8 +245,9 @@ def test_create_component_wizard_discovery_file_format_params(self) -> None: data["file_format_params"], {"properties_encoding": "utf-8"}, ) + self.assertEqual(data["language_regex"], "^(?!en$).+$") - file_format_params = data.pop("file_format_params") + file_format_params = cast("dict[str, str]", data.pop("file_format_params")) data.update( { f"file_format_params_{key}": value @@ -254,7 +256,6 @@ def test_create_component_wizard_discovery_file_format_params(self) -> None: ) data["project"] = self.project.pk data["source_language"] = get_default_lang() - data["language_regex"] = "^[^.]+$" data["new_base"] = "" data["new_lang"] = "contact" with override_settings(CREATE_GLOSSARIES=self.CREATE_GLOSSARIES): diff --git a/weblate/trans/tests/test_discovery.py b/weblate/trans/tests/test_discovery.py index 4eefcb04a08c..5be8c9dab6c7 100644 --- a/weblate/trans/tests/test_discovery.py +++ b/weblate/trans/tests/test_discovery.py @@ -5,7 +5,7 @@ import os import pathlib import tempfile -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, cast from unittest.mock import call, patch from django.test import SimpleTestCase @@ -490,8 +490,9 @@ def make_discovery_result( file_format: str = "", intermediate: str = "", new_base: str = "", + language_regex: str = "", ) -> DiscoveryResult: - data: ResultDict = {} + data: dict[str, object] = {} if name: data["name"] = name if filemask: @@ -504,8 +505,10 @@ def make_discovery_result( data["intermediate"] = intermediate if new_base: data["new_base"] = new_base + if language_regex: + data["language_regex"] = language_regex - result = DiscoveryResult(data) + result = DiscoveryResult(cast("ResultDict", data)) result.meta = {"priority": 1000, "origin": None} return result @@ -535,6 +538,43 @@ def test_detected_presets_deduplicate_discovery_results(self) -> None: "{{ component }}/values/strings.xml", ) + def test_detected_presets_preserve_language_regex(self) -> None: + first = self.make_discovery_result( + file_format="po", + filemask="django/conf/locale/*/LC_MESSAGES/messages.po", + new_base="django/conf/locale/en/LC_MESSAGES/messages.po", + language_regex="^(?!en$).+$", + ) + second = self.make_discovery_result( + file_format="po", + filemask="djangojs/conf/locale/*/LC_MESSAGES/messages.po", + new_base="djangojs/conf/locale/en/LC_MESSAGES/messages.po", + language_regex="^(?!en$).+$", + ) + + presets = get_detected_discovery_presets_from_results([first, second]) + + self.assertEqual(len(presets), 1) + self.assertEqual(presets[0]["values"]["language_regex"], "^(?!en$).+$") + + def test_detected_presets_do_not_combine_different_language_regexes(self) -> None: + first = self.make_discovery_result( + file_format="po", + filemask="django/conf/locale/*/LC_MESSAGES/messages.po", + new_base="django/conf/locale/en/LC_MESSAGES/messages.po", + language_regex="^(?!en$).+$", + ) + second = self.make_discovery_result( + file_format="po", + filemask="djangojs/conf/locale/*/LC_MESSAGES/messages.po", + new_base="djangojs/conf/locale/en_GB/LC_MESSAGES/messages.po", + language_regex="^(?!en_GB$).+$", + ) + + presets = get_detected_discovery_presets_from_results([first, second]) + + self.assertEqual(presets, []) + def test_detected_presets_keep_filename_suffix_from_translation_finder_cases( self, ) -> None: