diff --git a/config/locales/views/imports/en.yml b/config/locales/views/imports/en.yml index 1834927b7..be1676855 100644 --- a/config/locales/views/imports/en.yml +++ b/config/locales/views/imports/en.yml @@ -447,7 +447,6 @@ en: document_uploaded: Document uploaded successfully. document_upload_failed: We couldn't upload the document to the vector store. Please try again. invalid_ndjson_file_type: Invalid file type or format. Please upload a valid .ndjson or .json export file. - ndjson_uploaded: NDJSON file uploaded successfully. document_provider_not_configured: No vector store is configured for document uploads. show: finalize_upload: Please finalize your file upload. diff --git a/config/locales/views/securities/fr.yml b/config/locales/views/securities/fr.yml index 0afe46d6f..7591c0595 100644 --- a/config/locales/views/securities/fr.yml +++ b/config/locales/views/securities/fr.yml @@ -12,9 +12,4 @@ fr: tiingo: Tiingo twelve_data: Twelve Data yahoo_finance: Yahoo Finance - tiingo: Tiingo - eodhd: EODHD - alpha_vantage: Alpha Vantage - mfapi: MFAPI.in - binance_public: Binance moex_public: MOEX diff --git a/config/locales/views/settings/api_keys/hu.yml b/config/locales/views/settings/api_keys/hu.yml index ad0df2325..5d376caed 100644 --- a/config/locales/views/settings/api_keys/hu.yml +++ b/config/locales/views/settings/api_keys/hu.yml @@ -103,7 +103,6 @@ hu: created_label: "Létrehozva:" security_note_title: "Fontos biztonsági megjegyzés" security_note_body: "Ez az egyetlen alkalom, amikor az API-kulcsod megjelenik. Mindenképpen másold le most és tárold biztonságosan. Ha elveszíted, újat kell generálnod." - usage_instructions_title: "Az API-kulcs használata" key_name: "Név" permissions: "Jogosultságok" critical_warning_title: "⚠️ Kritikus: Mentsd el az API-kulcsodat most" diff --git a/config/locales/views/transactions/de.yml b/config/locales/views/transactions/de.yml index cacafb4f6..5c5846d32 100644 --- a/config/locales/views/transactions/de.yml +++ b/config/locales/views/transactions/de.yml @@ -97,7 +97,6 @@ de: mark_recurring_title: Wiederkehrende Transaktion potential_duplicate_title: Mögliches Duplikat erkannt potential_duplicate_description: Diese ausstehende Transaktion könnte mit der unten stehenden gebuchten Transaktion übereinstimmen. Wenn ja, führe sie zusammen, um Doppelzählung zu vermeiden. - merge_duplicate: Ja, zusammenführen keep_both: Nein, beide behalten transaction: pending: Ausstehend diff --git a/config/locales/views/transactions/en.yml b/config/locales/views/transactions/en.yml index 6f4162f0d..bd1a41606 100644 --- a/config/locales/views/transactions/en.yml +++ b/config/locales/views/transactions/en.yml @@ -127,7 +127,6 @@ en: mark_recurring_title: Recurring Transaction potential_duplicate_title: Possible duplicate detected potential_duplicate_description: This pending transaction may be the same as the posted transaction below. If so, merge them to avoid double-counting. - merge_duplicate: Yes, merge them keep_both: No, keep both split_parent_row: split_label: "Split" diff --git a/config/locales/views/transactions/hu.yml b/config/locales/views/transactions/hu.yml index 8eef07b97..69f03b4bc 100644 --- a/config/locales/views/transactions/hu.yml +++ b/config/locales/views/transactions/hu.yml @@ -123,7 +123,6 @@ hu: mark_recurring_title: Ismétlődő tranzakció potential_duplicate_title: Lehetséges duplikátum észlelve potential_duplicate_description: Ez a függőben lévő tranzakció megegyezhet az alábbi közzétett tranzakcióval. Ha igen, egyesítsd őket a kettős könyvelés elkerülése érdekében. - merge_duplicate: Igen, egyesítsd őket keep_both: Nem, mindkettőt tartsd meg split_parent_row: split_label: "Felosztva" diff --git a/config/locales/views/transactions/nl.yml b/config/locales/views/transactions/nl.yml index 6747ced06..4d2a3e168 100644 --- a/config/locales/views/transactions/nl.yml +++ b/config/locales/views/transactions/nl.yml @@ -71,7 +71,6 @@ nl: mark_recurring_title: Terugkerende Transactie potential_duplicate_title: Mogelijk duplicaat gedetecteerd potential_duplicate_description: Deze wachtende transactie kan hetzelfde zijn als de geposte transactie hieronder. Indien ja, voeg ze samen om dubbeltelling te voorkomen. - merge_duplicate: Ja, voeg ze samen keep_both: Nee, bewaar beide transaction: pending: Wachtend diff --git a/config/locales/views/transactions/uk.yml b/config/locales/views/transactions/uk.yml index 25485af7a..7f9aecf1e 100644 --- a/config/locales/views/transactions/uk.yml +++ b/config/locales/views/transactions/uk.yml @@ -122,7 +122,6 @@ uk: mark_recurring_title: Повторювана транзакція potential_duplicate_title: Виявлено можливий дублікат potential_duplicate_description: Ця очікувана транзакція може бути такою ж, як і опублікована транзакція нижче. Якщо так, об'єднайте їх, щоб уникнути подвійного підрахунку. - merge_duplicate: Так, об'єднати їх keep_both: Ні, залишити обидві split_parent_row: split_label: "Розділити" diff --git a/test/i18n_test.rb b/test/i18n_test.rb index 988089091..ce839345a 100644 --- a/test/i18n_test.rb +++ b/test/i18n_test.rb @@ -57,6 +57,26 @@ class I18nTest < ActiveSupport::TestCase assert_empty inconsistent_interpolations, error_message end + # YAML silently resolves duplicate keys by letting the last occurrence win, + # so a duplicated key shadows the earlier definition without any warning + # (see #1506 / #1502, where a stale `transactions.merge_duplicate` string + # shadowed — or was shadowed by — the `merge_duplicate.success/failure` + # mapping in several locales). Parse the raw YAML AST so duplicates can't + # sneak back in. + def test_no_duplicate_keys_within_locale_files + offenses = [] + + Dir[File.expand_path("../config/locales/**/*.yml", __dir__)].sort.each do |file| + Psych.parse_stream(File.read(file), filename: file).children.each do |doc| + offenses.concat(duplicate_key_offenses(doc.root, [], file)) + end + end + + assert_empty offenses, + "Duplicate keys found in locale files (the last occurrence silently wins):\n" \ + "#{offenses.map { |offense| " #{offense}" }.join("\n")}" + end + private def german_locale_paths @german_locale_paths ||= locale_paths.select { |path| path.basename.to_s.match?(/(^|[._-])de\.yml\z/) } @@ -65,4 +85,33 @@ class I18nTest < ActiveSupport::TestCase def locale_paths @locale_paths ||= GERMAN_COVERAGE_GLOBS.flat_map { |glob| Pathname.pwd.glob(glob) }.uniq end + + def duplicate_key_offenses(node, path, file) + offenses = [] + + case node + when Psych::Nodes::Mapping + first_definition_lines = {} + + node.children.each_slice(2) do |key_node, value_node| + if key_node.is_a?(Psych::Nodes::Scalar) + key_path = path + [ key_node.value ] + + if (first_line = first_definition_lines[key_node.value]) + offenses << "#{file}:#{key_node.start_line + 1} duplicate key `#{key_path.join(".")}` (first defined on line #{first_line})" + else + first_definition_lines[key_node.value] = key_node.start_line + 1 + end + + offenses.concat(duplicate_key_offenses(value_node, key_path, file)) + else + offenses.concat(duplicate_key_offenses(value_node, path, file)) + end + end + when Psych::Nodes::Sequence + node.children.each { |child| offenses.concat(duplicate_key_offenses(child, path, file)) } + end + + offenses + end end