Module: Jekyll::L10n::ExternalLinkIconPreserver

Defined in:
lib/jekyll-l10n/utils/external_link_icon_preserver.rb

Class Method Summary collapse

Class Method Details

.add_child_if_not_exists(child, translated_link) ⇒ Object



110
111
112
113
114
115
116
117
118
119
# File 'lib/jekyll-l10n/utils/external_link_icon_preserver.rb', line 110

def self.add_child_if_not_exists(child, translated_link)
  child_class = child['class'] || ''
  # Check if similar element already exists
  existing = translated_link.css("#{child.name}.#{child_class.split.first}").first
  return if existing

  # Add the element
  child_copy = child.dup
  translated_link.add_child(child_copy)
end

.preserve(original_html, translated_html) ⇒ String

Preserves external link icons from original HTML in translated HTML

External link icons (e.g., FontAwesome’s fa-external-link) are often lost during translation because:

  1. Block-level translation replaces entire element content

  2. Empty icon tags are removed during text extraction

This method restores icons by:

  1. Finding all i.fa-external-link icons in the original HTML

  2. Matching links by href attribute

  3. Copying icons to the translated HTML

Parameters:

  • original_html (String)

    Original HTML with icons

  • translated_html (String)

    Translated HTML potentially missing icons

Returns:

  • (String)

    Translated HTML with icons restored



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/jekyll-l10n/utils/external_link_icon_preserver.rb', line 24

def self.preserve(original_html, translated_html)
  # Use Nokogiri::HTML() instead of DocumentFragment.parse() to preserve the full
  # HTML document structure including DOCTYPE, html, head, and body tags.
  # DocumentFragment.parse() is appropriate for partial HTML only, and would strip
  # document-level structure.
  original_doc = Nokogiri::HTML(original_html)
  translated_doc = Nokogiri::HTML(translated_html)

  # Find all external link icons in original
  original_icons = original_doc.css('i.fa-external-link')
  return translated_html if original_icons.empty?

  # Process each icon found in the original HTML
  restore_icons_to_translated(original_icons, translated_doc)

  result = translated_doc.to_html

  # Remove the auto-inserted meta tag by libxml2 during HTML serialization
  HtmlParser.remove_meta_charset(result)
rescue StandardError => e
  Jekyll.logger.error 'Localization', "Error preserving external link icons: #{e.message}"
  translated_html
end

.preserve_all_inline_elements(original_html, translated_html) ⇒ String

Alternative method that preserves ALL inline elements, not just icons Useful for preserving SVG icons, badges, etc.

Parameters:

  • original_html (String)

    Original HTML

  • translated_html (String)

    Translated HTML

Returns:

  • (String)

    Translated HTML with all inline elements preserved



75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/jekyll-l10n/utils/external_link_icon_preserver.rb', line 75

def self.preserve_all_inline_elements(original_html, translated_html)
  original_doc = Nokogiri::HTML(original_html)
  translated_doc = Nokogiri::HTML(translated_html)

  # Find all links with child elements in original
  original_links = original_doc.css('a[href]')
  original_links.each do |original_link|
    preserve_link_inline_elements(original_link, translated_doc)
  end

  result = translated_doc.to_html
  HtmlParser.remove_meta_charset(result)
rescue StandardError => e
  Jekyll.logger.error 'Localization', "Error preserving inline elements: #{e.message}"
  translated_html
end


92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/jekyll-l10n/utils/external_link_icon_preserver.rb', line 92

def self.preserve_link_inline_elements(original_link, translated_doc)
  href = original_link['href']
  return unless href

  # Get all non-text children (i, svg, span, etc.)
  inline_children = original_link.children.select(&:element?)
  return if inline_children.empty?

  # Find matching link in translated version
  translated_link = translated_doc.css("a[href=\"#{href}\"]").first
  return unless translated_link

  # Append inline elements that don't already exist
  inline_children.each do |child|
    add_child_if_not_exists(child, translated_link)
  end
end

.restore_icons_to_translated(original_icons, translated_doc) ⇒ Object



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
# File 'lib/jekyll-l10n/utils/external_link_icon_preserver.rb', line 48

def self.restore_icons_to_translated(original_icons, translated_doc)
  original_icons.each do |icon|
    link = icon.parent
    next unless link&.name == 'a'

    href = link['href']
    next unless href

    # Find the same link in translated version
    translated_link = translated_doc.css("a[href=\"#{href}\"]").first
    next unless translated_link

    # Check if icon already exists
    next if translated_link.css('i.fa-external-link').any?

    # Add icon to translated link
    icon_copy = icon.dup
    translated_link.add_child(icon_copy)
  end
end