Module: Locallingo::Quality::StaticRules

Defined in:
lib/locallingo/quality/static_rules.rb

Overview

Regex-based, provider-free translation-quality rules. Ported from the original TranslationQualityChecker STATIC_RULES / UNIVERSAL_FIXES.

Constant Summary collapse

UNIVERSAL_FIXES =

Locale-agnostic auto-fixable corrections.

{
  "can not" => "cannot",
  "Can not" => "Cannot"
}.freeze
RULES =
{
  terminology: {
    /\bcan not\b/i => "Use 'cannot' (one word)",
    /\blogin\s+(to|regularly|now|here|again|first|using|with)\b/i =>
      "Use 'log in' (verb) not 'login' here",
    /\bclick\s+here\b/i => "Avoid 'click here' - use descriptive link text",
    /\bplease\b.*\bplease\b/i => "Multiple 'please' in same text - remove redundancy"
  },
  placeholders: {
    /%\{[^}]*\s[^}]*\}/ => "Placeholder contains spaces - may cause issues",
    /%\{[A-Z]/ => "Placeholder starts with uppercase - convention is lowercase"
  },
  clarity: {
    /\betc\.?\b/i => "Avoid 'etc.' - be specific or use 'and more'",
    /\bstuff\b/i => "Vague word 'stuff' - be more specific",
    /\bthings\b/i => "Vague word 'things' - be more specific",
    /\basap\b/i => "Avoid abbreviation 'ASAP' - use 'as soon as possible'",
    /\bfyi\b/i => "Avoid abbreviation 'FYI' - rephrase",
    /\s{2,}/ => "Multiple consecutive spaces"
  },
  business: {
    /\bsorry\b/i => "Consider 'We apologize' for formal business tone",
    /\boops\b/i => "Informal - use professional error messaging",
    /\buh\s*oh\b/i => "Informal - use professional error messaging",
    /\bawesome\b/i => "Consider more professional alternatives",
    /\bcool\b(?!\s*down)/i => "Informal - consider 'great' or 'excellent'"
  },
  accessibility: {
    /\bsee\s+below\b/i => "Screen reader unfriendly - describe the content",
    /\babove\b/i => "Positional reference - may not work for all users",
    /\bred\b.*\berror\b|\berror\b.*\bred\b/i => "Don't rely on color alone for meaning"
  }
}.freeze

Class Method Summary collapse

Class Method Details

.check(key, text, locale) ⇒ Object

Suggestions from the regex RULES for one key/text pair.



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/locallingo/quality/static_rules.rb', line 51

def check(key, text, locale)
  suggestions = []

  RULES.each do |category, rules|
    rules.each do |pattern, message|
      next unless text.match?(pattern)

      suggestions << {
        key:, text:, locale:, category:,
        issue: message,
        match: text.match(pattern).to_s,
        severity: severity_for_category(category),
        source: :static
      }
    end
  end

  suggestions
end

.severity_for_category(category) ⇒ Object



88
89
90
91
92
93
94
# File 'lib/locallingo/quality/static_rules.rb', line 88

def severity_for_category(category)
  case category
  when :placeholders then :error
  when :terminology, :accessibility then :warning
  else :info # :clarity, :business, :length, etc.
  end
end

.universal_fixes(key, text, locale) ⇒ Object

Auto-fixable universal fixes for one key/text pair.



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/locallingo/quality/static_rules.rb', line 72

def universal_fixes(key, text, locale)
  UNIVERSAL_FIXES.filter_map do |wrong, correct|
    next unless text.include?(wrong)

    {
      key:, text:, locale:,
      category: :grammar,
      issue: "Use '#{correct}' instead of '#{wrong}'",
      match: wrong,
      fix: { from: wrong, to: correct },
      severity: :warning,
      source: :static
    }
  end
end