jekyll-l10n 1.2.8 → 1.3.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +43 -63
  3. data/lib/jekyll-l10n/constants.rb +15 -10
  4. data/lib/jekyll-l10n/extraction/compendium_merger.rb +38 -17
  5. data/lib/jekyll-l10n/extraction/compendium_translator.rb +18 -18
  6. data/lib/jekyll-l10n/extraction/config_loader.rb +8 -8
  7. data/lib/jekyll-l10n/extraction/dom_attribute_extractor.rb +4 -4
  8. data/lib/jekyll-l10n/extraction/dom_text_extractor.rb +6 -6
  9. data/lib/jekyll-l10n/extraction/extractor.rb +15 -15
  10. data/lib/jekyll-l10n/extraction/html_string_extractor.rb +5 -5
  11. data/lib/jekyll-l10n/extraction/logger.rb +6 -6
  12. data/lib/jekyll-l10n/extraction/result_saver.rb +12 -12
  13. data/lib/jekyll-l10n/jekyll/generator.rb +25 -13
  14. data/lib/jekyll-l10n/jekyll/localized_page.rb +13 -13
  15. data/lib/jekyll-l10n/jekyll/post_write_html_reprocessor.rb +14 -14
  16. data/lib/jekyll-l10n/jekyll/post_write_processor.rb +19 -6
  17. data/lib/jekyll-l10n/jekyll/regeneration_checker.rb +10 -10
  18. data/lib/jekyll-l10n/jekyll/url_filter.rb +17 -17
  19. data/lib/jekyll-l10n/po_file/loader.rb +4 -4
  20. data/lib/jekyll-l10n/po_file/manager.rb +15 -15
  21. data/lib/jekyll-l10n/po_file/merger.rb +3 -3
  22. data/lib/jekyll-l10n/po_file/path_builder.rb +1 -1
  23. data/lib/jekyll-l10n/po_file/reader.rb +42 -50
  24. data/lib/jekyll-l10n/po_file/writer.rb +20 -20
  25. data/lib/jekyll-l10n/translation/block_text_extractor.rb +5 -5
  26. data/lib/jekyll-l10n/translation/html_translator.rb +22 -22
  27. data/lib/jekyll-l10n/translation/libre_translator.rb +29 -26
  28. data/lib/jekyll-l10n/translation/page_translation_loader.rb +8 -8
  29. data/lib/jekyll-l10n/translation/translator.rb +26 -26
  30. data/lib/jekyll-l10n/utils/debug_logger.rb +6 -6
  31. data/lib/jekyll-l10n/utils/error_handler.rb +2 -2
  32. data/lib/jekyll-l10n/utils/external_link_icon_preserver.rb +11 -11
  33. data/lib/jekyll-l10n/utils/file_operations.rb +5 -5
  34. data/lib/jekyll-l10n/utils/html_elements.rb +5 -5
  35. data/lib/jekyll-l10n/utils/html_parser.rb +2 -2
  36. data/lib/jekyll-l10n/utils/html_text_utils.rb +12 -12
  37. data/lib/jekyll-l10n/utils/logger_formatter.rb +6 -6
  38. data/lib/jekyll-l10n/utils/page_locales_config.rb +36 -35
  39. data/lib/jekyll-l10n/utils/po_entry_converter.rb +10 -12
  40. data/lib/jekyll-l10n/utils/site_config_accessor.rb +4 -4
  41. data/lib/jekyll-l10n/utils/text_normalizer.rb +2 -2
  42. data/lib/jekyll-l10n/utils/text_validator.rb +1 -1
  43. data/lib/jekyll-l10n/utils/translation_resolver.rb +3 -3
  44. data/lib/jekyll-l10n/utils/url_path_builder.rb +5 -5
  45. data/lib/jekyll-l10n/utils/url_transformer.rb +13 -13
  46. data/lib/jekyll-l10n/utils/xpath_reference_generator.rb +2 -2
  47. data/lib/jekyll-l10n/version.rb +1 -1
  48. data/lib/jekyll-l10n.rb +48 -48
  49. metadata +60 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5a4a4261253d5efb8103b3d8896bff9960249f4d6ed69266c0016729b38da43
4
- data.tar.gz: 582bb044c024621b3bee6407f0ef6f2c6d3f3de8cbca9df14c2449702aaeb446
3
+ metadata.gz: e9b061ddf1f9f9072efe9135d023d05d55d7dd8545bd34988ecae6f59e03a2e2
4
+ data.tar.gz: 6c8704fa0e33e96c8e9918d5f7539db8203f291b4a2608e8946846e86fea8a94
5
5
  SHA512:
6
- metadata.gz: cb0212b0e62d331499629fe94eb3983dbaba9d4414804be1f1846873619935acbecf8f26d405b5c10cdc4400bdd246c23f35697ab67bc58deae24b506280f516
7
- data.tar.gz: dde77b84bb811f0e08fb3bf4cf613cc8cef18bb39e907c7b0bf53a6c0993e33c399bf8b089cab60cbbe5e597725616aae1575b2c21fc9372c299759430c393ba
6
+ metadata.gz: 709ab40d1a6f0ada0810751f54279d4c466d00349a46a9c7916d4a705289af6e8c142ebbd31fefd520c1205089f1f662354f702b381fe8bb44129ab4fde157fc
7
+ data.tar.gz: acda3c29b32433e2c3b1e90004690955b0da0219a8c896f8cfc28aa61e2ff190e238352e08e35cd606c4717524b8d6c731cd3efac673be115ec89ce89a9fdb32
data/README.md CHANGED
@@ -1,85 +1,65 @@
1
1
  # jekyll-l10n
2
2
 
3
- `jekyll-l10n` is a Jekyll plugin that streamlines the localization of static
4
- websites using industry-standard GNU Gettext PO files. Creating multilingual
5
- sites presents unique challenges: maintaining consistent translations across
6
- multiple pages, managing translation workflows with non-technical translators,
7
- and keeping translations synchronized as content evolves. This plugin automates
8
- these challenges by integrating the proven Gettext workflow directly into your
9
- Jekyll build pipeline.
10
-
11
- The plugin works by extracting translatable strings from your site's generated
12
- HTML and organizing them into PO files that translators can edit using standard
13
- translation tools. As your content changes, the plugin intelligently updates
14
- these translation files, preserving existing translations while flagging
15
- changed or new content. When you rebuild your site, translated strings are
16
- automatically applied to localized versions of your pages, producing fully
17
- translated HTML output with locale-prefixed URLs.
3
+ `jekyll-l10n` is a Jekyll plugin that streamlines the localization of static websites using industry-standard GNU Gettext PO files. It extracts translatable strings from your site's HTML, organizes them into PO files for professional translation, and automatically applies translations to generate fully localized pages with locale-prefixed URLs.
18
4
 
19
5
  ![Jekyll site localization](docs/assets/img/jekyll-l10n.png)
20
6
 
21
- Key features include automatic page duplication with locale-specific URL
22
- prefixes, flexible fallback modes when translations are incomplete (display
23
- original English, mark untranslated strings, or leave blank), and support for
24
- compendium files to share common translations across your site. By leveraging
25
- the standard Gettext format and workflow, `jekyll-l10n` enables collaboration
26
- with professional translators and integrates with existing translation
27
- management systems, while keeping your source content in Markdown where it
28
- belongs.
7
+ ## Installation
29
8
 
30
- ## Development Setup
9
+ Add to your Jekyll site's `Gemfile`:
31
10
 
32
- To set up your development environment:
33
-
34
- ```bash
35
- bundle install # Install Ruby dependencies
36
- pip install pre-commit # Install pre-commit framework
37
- pre-commit install # Install pre-commit hooks
11
+ ```ruby
12
+ gem "jekyll-l10n", "~> 1.1"
38
13
  ```
39
14
 
40
- This enables pre-commit hooks that automatically check code style and format on each commit.
15
+ Run `bundle install`, then enable in `_config.yml`:
41
16
 
42
- ## Configuration
17
+ ```yaml
18
+ plugins:
19
+ - jekyll-l10n
20
+
21
+ defaults:
22
+ - scope:
23
+ type: "pages"
24
+ values:
25
+ with_locales: true
26
+ with_locales_data:
27
+ locales: ["es", "fr", "de"]
28
+ locales_dir: "_locales"
29
+ extract_on_build: true
30
+ ```
43
31
 
44
- ### Incremental Builds (Performance Optimization)
32
+ ## Quick Example
45
33
 
46
- By default, the plugin regenerates all localized pages on every build. For large
47
- sites with many locales, this can impact build performance. You can enable
48
- incremental build support to skip regenerating pages that haven't changed:
34
+ Edit PO files in `_locales/` with translations. On rebuild, your site will generate:
49
35
 
50
- ```yaml
51
- localization_gettext:
52
- with_locales_data:
53
- incremental: true # Enable incremental builds
54
- ```
36
+ - `/es/` - Spanish pages
37
+ - `/fr/` - French pages
38
+ - `/de/` - German pages
55
39
 
56
- Or at the top level:
40
+ ## Documentation
57
41
 
58
- ```yaml
59
- localization_gettext:
60
- incremental: true
61
- ```
42
+ Complete documentation is available in the [docs/](docs/) directory:
62
43
 
63
- When incremental mode is enabled, pages are only regenerated if:
44
+ - **[Getting Started](docs/getting-started/)** - Installation requirements and first-site setup
45
+ - **[Configuration Guide](docs/configuration/)** - All configuration options and settings
46
+ - **[Guides](docs/guides/)** - Fallback modes, Liquid filters, machine translation, incremental builds
47
+ - **[Development](docs/development/)** - Setup, testing, API documentation
48
+ - **[Examples](docs/examples/)** - Real-world usage examples
64
49
 
65
- - The source page content has been modified
66
- - Any PO translation files have been updated
67
- - The Jekyll configuration has changed
50
+ ## Key Features
68
51
 
69
- This significantly improves build times on subsequent builds when only
70
- translations or a few pages have changed.
52
+ - **Automatic extraction** - Extract translatable strings during Jekyll builds
53
+ - **Professional workflows** - Edit translations using standard Gettext tools (Poedit, Weblate, etc.)
54
+ - **Fallback modes** - Display English, mark untranslated strings, or leave blank
55
+ - **Incremental builds** - Skip regenerating unchanged localized pages for faster builds
56
+ - **Machine translation** - Optional LibreTranslate integration for initial translations
57
+ - **Compendium files** - Share common translations across your entire site
71
58
 
72
- ## Machine Translation
59
+ ## Requirements
73
60
 
74
- For teams without translation resources, the plugin integrates with
75
- LibreTranslate, a free and open-source machine translation service, to
76
- automatically translate newly extracted strings during the extraction workflow.
77
- You can enable this optional integration on a per-locale basis, allowing
78
- LibreTranslate to generate initial translations for compendia files that serve
79
- as a foundation for professional translators to refine. This significantly
80
- reduces the initial translation effort and helps bootstrap localization for new
81
- content, though professional review is still recommended for
82
- publication-quality results.
61
+ - **Ruby**: >= 2.7.0
62
+ - **Jekyll**: >= 4.0, < 5.0
83
63
 
84
64
  ## License
85
65
 
@@ -88,7 +68,7 @@ MIT License - see LICENSE file for details.
88
68
  ## Contributing
89
69
 
90
70
  1. Fork the repository
91
- 2. Create your feature branch (`git checkout -b feature/amazing-feature`)
71
+ 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
92
72
  3. Commit your changes (`git commit -m 'feat: Add amazing feature'`)
93
73
  4. Push to the branch (`git push origin feature/amazing-feature`)
94
74
  5. Open a Pull Request
@@ -22,27 +22,27 @@ module Jekyll
22
22
  # Matches ISO 639-1 (2 letter language) with optional ISO 3166-1 (2 letter country)
23
23
  # Examples: 'en', 'es', 'fr', 'pt_BR', 'zh_CN'
24
24
  # @return [Regexp]
25
- LOCALE_PATTERN = %r!^[a-z]{2}(_[A-Z]{2})?$!.freeze
25
+ LOCALE_PATTERN = /^[a-z]{2}(_[A-Z]{2})?$/.freeze
26
26
 
27
27
  # ## Translation Fallback Modes
28
28
 
29
29
  # Fallback mode: use original English text if translation not found
30
30
  # @return [String] "english"
31
- FALLBACK_MODE_ENGLISH = "english"
31
+ FALLBACK_MODE_ENGLISH = 'english'
32
32
 
33
- # Fallback mode: wrap untranslated text with markers (e.g., "[UNTRANSLATED: text]")
33
+ # Fallback mode: wrap untranslated text with markers (e.g., "[UNTRANSLATED] text")
34
34
  # @return [String] "marker"
35
- FALLBACK_MODE_MARKER = "marker"
35
+ FALLBACK_MODE_MARKER = 'marker'
36
36
 
37
37
  # Fallback mode: leave text blank if no translation found
38
38
  # @return [String] "empty"
39
- FALLBACK_MODE_EMPTY = "empty"
39
+ FALLBACK_MODE_EMPTY = 'empty'
40
40
 
41
41
  # ## Translation Markers
42
42
 
43
43
  # Marker used to indicate untranslated strings in marker fallback mode
44
44
  # @return [String] "[UNTRANSLATED]"
45
- UNTRANSLATED_MARKER = "[UNTRANSLATED]"
45
+ UNTRANSLATED_MARKER = '[UNTRANSLATED]'
46
46
 
47
47
  # ## PO File Formatting (GNU Gettext Standard)
48
48
 
@@ -82,7 +82,7 @@ module Jekyll
82
82
 
83
83
  # Default directory for storing PO translation files
84
84
  # @return [String] "_locales"
85
- DEFAULT_LOCALES_DIR = "_locales"
85
+ DEFAULT_LOCALES_DIR = '_locales'
86
86
 
87
87
  # Default fallback mode when translation is not found
88
88
  # @return [String] "english"
@@ -90,10 +90,15 @@ module Jekyll
90
90
 
91
91
  # Default HTML attributes to extract from elements (can be overridden per-page)
92
92
  # @return [Array<String>] ["title", "alt", "aria-label", "placeholder", "aria-description"]
93
- DEFAULT_TRANSLATABLE_ATTRIBUTES = %w(title alt aria-label placeholder aria-description).freeze
93
+ DEFAULT_TRANSLATABLE_ATTRIBUTES = %w[title alt aria-label placeholder aria-description].freeze
94
94
 
95
95
  # ## LibreTranslate Integration Defaults
96
96
 
97
+ # Default LibreTranslate API endpoint URL
98
+ # Uses localhost:5000 as default for local development
99
+ # @return [String] "http://localhost:5000"
100
+ DEFAULT_LIBRETRANSLATE_API_URL = 'http://localhost:5000'
101
+
97
102
  # Default timeout (in seconds) for LibreTranslate API requests
98
103
  # @return [Integer] 300 seconds (5 minutes)
99
104
  DEFAULT_LIBRETRANSLATE_TIMEOUT = 300
@@ -125,12 +130,12 @@ module Jekyll
125
130
  # Default source locale for LibreTranslate API
126
131
  # The language of the original content being translated
127
132
  # @return [String] "en" (English)
128
- DEFAULT_LIBRETRANSLATE_SOURCE_LOCALE = "en"
133
+ DEFAULT_LIBRETRANSLATE_SOURCE_LOCALE = 'en'
129
134
 
130
135
  # Default text format for LibreTranslate API requests
131
136
  # Either 'text' (plain text) or 'html' (preserves markup)
132
137
  # @return [String] "html"
133
- DEFAULT_LIBRETRANSLATE_FORMAT = "html"
138
+ DEFAULT_LIBRETRANSLATE_FORMAT = 'html'
134
139
  end
135
140
  end
136
141
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../po_file/manager"
4
- require_relative "../utils/page_locales_config"
5
- require_relative "../utils/site_config_accessor"
3
+ require_relative '../po_file/manager'
4
+ require_relative '../utils/page_locales_config'
5
+ require_relative '../utils/site_config_accessor'
6
6
 
7
7
  module Jekyll
8
8
  module L10n
@@ -34,7 +34,7 @@ module Jekyll
34
34
  def initialize(site)
35
35
  @site = site
36
36
  with_locales_data = SiteConfigAccessor.extract_locales_data(@site)
37
- @site_config = PageLocalesConfig.new({ "with_locales_data" => with_locales_data })
37
+ @site_config = PageLocalesConfig.new({ 'with_locales_data' => with_locales_data })
38
38
  end
39
39
 
40
40
  # Merge page-specific PO files into compendia for all locales.
@@ -55,6 +55,7 @@ module Jekyll
55
55
  private
56
56
 
57
57
  # Process a single locale: merge existing compendium with new page translations
58
+ # Skips writing when translations are unchanged to avoid unnecessary file rewrites
58
59
  def process_locale(locale, po_manager, config)
59
60
  compendium_path = File.join(@site.source, config.locales_dir, "#{locale}.po")
60
61
  existing_compendium = load_existing_compendium(compendium_path)
@@ -62,12 +63,27 @@ module Jekyll
62
63
 
63
64
  combined = build_combined_hash(existing_compendium)
64
65
  merge_into_combined(combined, merged)
65
- combined_entries = format_compendium_entries(combined)
66
66
 
67
- po_manager.save_compendium(locale, combined_entries)
67
+ unless compendium_unchanged?(existing_compendium, combined)
68
+ combined_entries = format_compendium_entries(combined)
69
+ po_manager.save_compendium(locale, combined_entries)
70
+ end
68
71
  cleanup_locale_directory(locale, config)
69
72
  end
70
73
 
74
+ # Check if compendium content is unchanged (same msgids and msgstrs)
75
+ def compendium_unchanged?(existing_compendium, combined)
76
+ return false if existing_compendium.empty? && !combined.empty?
77
+
78
+ normalized_existing = build_combined_hash(existing_compendium)
79
+ return false unless normalized_existing.keys.sort == combined.keys.sort
80
+
81
+ combined.all? do |msgid, data|
82
+ existing = normalized_existing[msgid]
83
+ existing && existing[:msgstr] == data[:msgstr]
84
+ end
85
+ end
86
+
71
87
  # Load existing compendium translations or return empty hash if not found
72
88
  def load_existing_compendium(compendium_path)
73
89
  if File.exist?(compendium_path)
@@ -89,9 +105,9 @@ module Jekyll
89
105
  # Normalize entry format to ensure consistent hash structure with :msgstr and :reference keys
90
106
  def normalize_compendium_entry(data)
91
107
  if data.is_a?(Hash)
92
- { :msgstr => data[:msgstr], :reference => data[:reference] }
108
+ { msgstr: data[:msgstr], reference: data[:reference] }
93
109
  else
94
- { :msgstr => data, :reference => nil }
110
+ { msgstr: data, reference: nil }
95
111
  end
96
112
  end
97
113
 
@@ -108,20 +124,24 @@ module Jekyll
108
124
 
109
125
  # Update reference for existing entry if new reference is available
110
126
  def update_entry_reference(combined_entry, entry)
111
- if combined_entry[:reference].nil? && entry.is_a?(Hash) && entry[:reference]
112
- combined_entry[:reference] = entry[:reference]
113
- end
127
+ return unless combined_entry[:reference].nil? && entry.is_a?(Hash) && entry[:reference]
128
+
129
+ combined_entry[:reference] = entry[:reference]
114
130
  end
115
131
 
116
- # Create new entry for untranslated string with optional reference
132
+ # Create new entry preserving any existing translation and reference
117
133
  def create_new_entry(entry)
118
- { :msgstr => "", :reference => entry.is_a?(Hash) ? entry[:reference] : nil }
134
+ if entry.is_a?(Hash)
135
+ { msgstr: entry[:msgstr] || '', reference: entry[:reference] }
136
+ else
137
+ { msgstr: '', reference: nil }
138
+ end
119
139
  end
120
140
 
121
141
  # Convert combined hash to array of entries suitable for PO file writing
122
142
  def format_compendium_entries(combined)
123
143
  combined.map do |msgid, data|
124
- entry = { :msgid => msgid, :msgstr => data[:msgstr] }
144
+ entry = { msgid: msgid, msgstr: data[:msgstr] }
125
145
  entry[:reference] = data[:reference] if data[:reference]
126
146
  entry
127
147
  end
@@ -134,9 +154,10 @@ module Jekyll
134
154
  FileUtils.rm_rf(locale_dir) if File.directory?(locale_dir)
135
155
  end
136
156
 
137
- private :process_locale, :load_existing_compendium, :build_combined_hash,
138
- :normalize_compendium_entry, :merge_into_combined, :update_entry_reference,
139
- :create_new_entry, :format_compendium_entries, :cleanup_locale_directory
157
+ private :process_locale, :compendium_unchanged?, :load_existing_compendium,
158
+ :build_combined_hash, :normalize_compendium_entry, :merge_into_combined,
159
+ :update_entry_reference, :create_new_entry, :format_compendium_entries,
160
+ :cleanup_locale_directory
140
161
  end
141
162
  end
142
163
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../po_file/manager"
4
- require_relative "../utils/page_locales_config"
5
- require_relative "../utils/po_entry_converter"
6
- require_relative "../utils/site_config_accessor"
7
- require_relative "../utils/logger_formatter"
8
- require_relative "../translation/libre_translator"
3
+ require_relative '../po_file/manager'
4
+ require_relative '../utils/page_locales_config'
5
+ require_relative '../utils/po_entry_converter'
6
+ require_relative '../utils/site_config_accessor'
7
+ require_relative '../utils/logger_formatter'
8
+ require_relative '../translation/libre_translator'
9
9
 
10
10
  module Jekyll
11
11
  module L10n
@@ -34,7 +34,7 @@ module Jekyll
34
34
  def initialize(site)
35
35
  @site = site
36
36
  with_locales_data = SiteConfigAccessor.extract_locales_data(@site)
37
- @site_config = PageLocalesConfig.new({ "with_locales_data" => with_locales_data })
37
+ @site_config = PageLocalesConfig.new({ 'with_locales_data' => with_locales_data })
38
38
  end
39
39
 
40
40
  # Translate compendia for all configured locales.
@@ -68,7 +68,7 @@ module Jekyll
68
68
 
69
69
  def process_single_locale(locale, config, translator, po_manager)
70
70
  compendium_path = File.join(@site.source, config.locales_dir, "#{locale}.po")
71
- LoggerFormatter.debug_if_enabled("CompendiumTranslator",
71
+ LoggerFormatter.debug_if_enabled('CompendiumTranslator',
72
72
  "Processing compendium file: #{compendium_path}")
73
73
  return unless File.exist?(compendium_path)
74
74
 
@@ -86,29 +86,29 @@ module Jekyll
86
86
  end
87
87
 
88
88
  def log_compendia_enabled_check(enabled)
89
- msg = "translate_compendia_for_locale called, libretranslate_enabled:"
90
- LoggerFormatter.debug_if_enabled("CompendiumTranslator", "#{msg} #{enabled}")
89
+ msg = 'translate_compendia_for_locale called, libretranslate_enabled:'
90
+ LoggerFormatter.debug_if_enabled('CompendiumTranslator', "#{msg} #{enabled}")
91
91
  end
92
92
 
93
93
  def log_compendium_stats(locale, po_entries, compendium_path)
94
94
  msg = "Locale #{locale}: Loaded #{po_entries.length} entries from compendium"
95
- LoggerFormatter.debug_if_enabled("CompendiumTranslator", "#{msg} #{compendium_path}")
95
+ LoggerFormatter.debug_if_enabled('CompendiumTranslator', "#{msg} #{compendium_path}")
96
96
 
97
97
  empty_count = count_empty_entries(po_entries)
98
98
  LoggerFormatter.debug_if_enabled(
99
- "CompendiumTranslator",
99
+ 'CompendiumTranslator',
100
100
  "Locale #{locale}: #{empty_count} empty msgstr entries to translate"
101
101
  )
102
102
  end
103
103
 
104
104
  def log_translation_complete_for_locale(locale)
105
105
  msg = "Locale #{locale}: Translation complete, saving compendium"
106
- LoggerFormatter.debug_if_enabled("CompendiumTranslator", msg)
106
+ LoggerFormatter.debug_if_enabled('CompendiumTranslator', msg)
107
107
  end
108
108
 
109
109
  def log_compendium_saved(locale, compendium_path)
110
110
  msg = "Locale #{locale}: Saved compendium to"
111
- LoggerFormatter.debug_if_enabled("CompendiumTranslator", "#{msg} #{compendium_path}")
111
+ LoggerFormatter.debug_if_enabled('CompendiumTranslator', "#{msg} #{compendium_path}")
112
112
  end
113
113
 
114
114
  def count_empty_entries(po_entries)
@@ -118,14 +118,14 @@ module Jekyll
118
118
  end
119
119
 
120
120
  def log_translation_start(config)
121
- locales = config.locales.join(", ")
122
- Jekyll.logger.info "Localization",
121
+ locales = config.locales.join(', ')
122
+ Jekyll.logger.info 'Localization',
123
123
  "Starting LibreTranslate translation for locales: #{locales}"
124
124
  end
125
125
 
126
126
  def log_translation_complete(config)
127
- locales = config.locales.join(", ")
128
- Jekyll.logger.info "Localization",
127
+ locales = config.locales.join(', ')
128
+ Jekyll.logger.info 'Localization',
129
129
  "LibreTranslate translation complete for locales: #{locales}"
130
130
  end
131
131
 
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../utils/page_locales_config"
3
+ require_relative '../utils/page_locales_config'
4
4
 
5
5
  module Jekyll
6
6
  module L10n
@@ -69,10 +69,10 @@ module Jekyll
69
69
  # @return [Hash, nil] Page front matter data if found, nil otherwise
70
70
  def find_page_config_for_file(file_path)
71
71
  @site.pages.each do |page|
72
- next unless page.data["with_locales"] == true
72
+ next unless page.data['with_locales'] == true
73
73
 
74
- page_output = page.output_ext ? page.destination("") : page.destination("/")
75
- next unless file_path.end_with?(page_output.sub(%r!/$!, "/index.html"))
74
+ page_output = page.output_ext ? page.destination('') : page.destination('/')
75
+ next unless file_path.end_with?(page_output.sub(%r{/$}, '/index.html'))
76
76
 
77
77
  return page.data
78
78
  end
@@ -88,10 +88,10 @@ module Jekyll
88
88
  # @param file_path [String] Path to file to check
89
89
  # @return [Boolean] True if file is in a locale subdirectory
90
90
  def skip_localized_page?(file_path)
91
- relative_path = file_path.sub(@dest, "")
91
+ relative_path = file_path.sub(@dest, '')
92
92
 
93
93
  all_locales = @site.pages.map do |p|
94
- p.data.dig("with_locales_data", "locales") || []
94
+ p.data.dig('with_locales_data', 'locales') || []
95
95
  end
96
96
  all_locales.flatten!
97
97
  all_locales.uniq!
@@ -106,8 +106,8 @@ module Jekyll
106
106
  # @param config [Hash] Page front matter data
107
107
  # @return [Array<String>] CSS selectors for excluded elements
108
108
  def extract_exclude_selectors(config)
109
- config.data.dig("with_locales_data", "extraction", "exclude_selectors") ||
110
- ["script", "style", "code.language-plaintext", "pre code"]
109
+ config.data.dig('with_locales_data', 'extraction', 'exclude_selectors') ||
110
+ ['script', 'style', 'code.language-plaintext', 'pre code']
111
111
  end
112
112
  end
113
113
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../utils/xpath_reference_generator"
4
- require_relative "../utils/text_validator"
3
+ require_relative '../utils/xpath_reference_generator'
4
+ require_relative '../utils/text_validator'
5
5
 
6
6
  module Jekyll
7
7
  module L10n
@@ -24,7 +24,7 @@ module Jekyll
24
24
  # ['title', 'alt', 'aria-label'])
25
25
  # # Returns array of extraction entries for all valid attribute values
26
26
  module DomAttributeExtractor
27
- extend self
27
+ module_function
28
28
 
29
29
  # Extract attribute values from an HTML element.
30
30
  #
@@ -47,7 +47,7 @@ module Jekyll
47
47
  attrs = extract_node_attributes(node, translatable_attrs)
48
48
  attrs.map do |attr_text, attr_name|
49
49
  reference = XPathReferenceGenerator.generate(node, file_path, dest, attr_name)
50
- { :msgid => attr_text, :msgstr => "", :reference => reference }
50
+ { msgid: attr_text, msgstr: '', reference: reference }
51
51
  end
52
52
  end
53
53
 
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "../utils/text_normalizer"
4
- require_relative "../utils/xpath_reference_generator"
5
- require_relative "../utils/html_text_utils"
6
- require_relative "../utils/html_elements"
7
- require_relative "../utils/text_validator"
3
+ require_relative '../utils/text_normalizer'
4
+ require_relative '../utils/xpath_reference_generator'
5
+ require_relative '../utils/html_text_utils'
6
+ require_relative '../utils/html_elements'
7
+ require_relative '../utils/text_validator'
8
8
 
9
9
  module Jekyll
10
10
  module L10n
@@ -48,7 +48,7 @@ module Jekyll
48
48
  return nil if text.nil?
49
49
 
50
50
  reference = XPathReferenceGenerator.generate(node, file_path, dest)
51
- { :msgid => text, :msgstr => "", :reference => reference }
51
+ { msgid: text, msgstr: '', reference: reference }
52
52
  end
53
53
 
54
54
  def extractable?(node)
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "config_loader"
4
- require_relative "result_saver"
5
- require_relative "logger"
6
- require_relative "html_string_extractor"
7
- require_relative "../utils/file_operations"
8
- require_relative "../utils/site_config_accessor"
9
- require_relative "../utils/error_handler"
3
+ require_relative 'config_loader'
4
+ require_relative 'result_saver'
5
+ require_relative 'logger'
6
+ require_relative 'html_string_extractor'
7
+ require_relative '../utils/file_operations'
8
+ require_relative '../utils/site_config_accessor'
9
+ require_relative '../utils/error_handler'
10
10
 
11
11
  module Jekyll
12
12
  module L10n
@@ -72,7 +72,7 @@ module Jekyll
72
72
  # result = extractor.extract_site
73
73
  # puts "Processed #{result[:files_processed]} files"
74
74
  def extract_site
75
- Jekyll.logger.info "Localization", "Extracting translatable strings..."
75
+ Jekyll.logger.info 'Localization', 'Extracting translatable strings...'
76
76
  start_time = Time.now
77
77
  stats = process_all_html_files
78
78
  translate_all_compendia
@@ -81,8 +81,8 @@ module Jekyll
81
81
  end
82
82
 
83
83
  def process_all_html_files
84
- stats = { :files_processed => 0, :strings_extracted => 0, :po_files_created => 0 }
85
- html_files = Dir.glob(File.join(@dest, "**", "*.html"))
84
+ stats = { files_processed: 0, strings_extracted: 0, po_files_created: 0 }
85
+ html_files = Dir.glob(File.join(@dest, '**', '*.html'))
86
86
 
87
87
  html_files.each do |file_path|
88
88
  next if @config_loader.skip_localized_page?(file_path)
@@ -100,7 +100,7 @@ module Jekyll
100
100
  config = find_libretranslate_config
101
101
  return unless config
102
102
 
103
- ErrorHandler.handle_with_logging("machine translation") do
103
+ ErrorHandler.handle_with_logging('machine translation') do
104
104
  @result_saver.translate_compendia(config)
105
105
  end
106
106
  end
@@ -120,7 +120,7 @@ module Jekyll
120
120
  end
121
121
 
122
122
  def default_stats
123
- { :files_processed => 0, :strings_extracted => 0, :po_files_created => 0 }
123
+ { files_processed: 0, strings_extracted: 0, po_files_created: 0 }
124
124
  end
125
125
 
126
126
  def extract_strings_from_file(file_path, config)
@@ -137,9 +137,9 @@ module Jekyll
137
137
  return nil unless @site.respond_to?(:pages)
138
138
 
139
139
  @site.pages.each do |page|
140
- next unless page.data["with_locales"] == true
140
+ next unless page.data['with_locales'] == true
141
141
 
142
- config = @config_loader.load_page_config(page.destination(""))
142
+ config = @config_loader.load_page_config(page.destination(''))
143
143
  return config if config.libretranslate_enabled?
144
144
  end
145
145
 
@@ -149,7 +149,7 @@ module Jekyll
149
149
  private
150
150
 
151
151
  def construct_page_path(file_path)
152
- file_path.sub("#{@dest}/", "")
152
+ file_path.sub("#{@dest}/", '')
153
153
  end
154
154
  end
155
155
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "dom_text_extractor"
4
- require_relative "dom_attribute_extractor"
5
- require_relative "logger"
3
+ require_relative 'dom_text_extractor'
4
+ require_relative 'dom_attribute_extractor'
5
+ require_relative 'logger'
6
6
 
7
7
  module Jekyll
8
8
  module L10n
@@ -92,10 +92,10 @@ module Jekyll
92
92
 
93
93
  @exclude_selectors.any? { |selector| node.matches?(selector) }
94
94
  rescue Nokogiri::CSS::SyntaxError => e
95
- Jekyll.logger.warn "Localization", "CSS selector syntax error: #{e.message}"
95
+ Jekyll.logger.warn 'Localization', "CSS selector syntax error: #{e.message}"
96
96
  false
97
97
  rescue StandardError => e
98
- Jekyll.logger.warn "Localization", "Selector matching error (continuing): #{e.message}"
98
+ Jekyll.logger.warn 'Localization', "Selector matching error (continuing): #{e.message}"
99
99
  false
100
100
  end
101
101
  end