Zum Hauptinhalt springen
Echtzeit-Radar & Feeds
Alle RSS Feeds ➔
👥 Community & Social
Windows Tipps & SecurityGrafikkarte vor Überhitzung schützen: So geht’s(25.09.2026 um 08:00 Uhr)
••••••••••
Windows Tipps & SecurityGrafikkarte vor Überhitzung schützen: So geht’s(25.09.2026 um 08:00 Uhr)
••••••••••
Intelligence View
⚡ tsecurity.de Intelligence

Custom translations per tenant in a Rails app thanks to I18n backends

When building a SaaS or any multi-tenant application, it is common to want to adapt certain translation keys for certain customers, in order to provide a truly customized experience. In this article, we'll see a very powerful yet easy way…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

When building a SaaS or any multi-tenant application, it is common to want to adapt certain translation keys for certain customers, in order to provide a truly customized experience. In this article, we'll see a very powerful yet easy way to achieve it thanks to I18n backends in any Rails app.



The i18n lib in ruby works with "backends". Given a specific key and locale, they are tasked with retrieving the correct translation key. The default backend is I18n::Backend::Simple, which looks at the translations in YML files stored in config/locales, but it is possible to create custom backends and even chain them to find translations in different places with a sense of priority.






Identifying the current customer / tenant



Rails provide us with the great Current class that allows us to store variables scoped to the current HTTP request. If your application is already multi-tenant capable, you probably already have something similar :




# app/models/current.rb
class Current < ActiveSupport::CurrentAttributes
attribute :tenant
attribute :user
end

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :set_current_tenant

# ...
def set_current_tenant
Current.tenant = current_user.tenant
end
end









Solution 1: store custom keys in the YML files directly



The simplest approach is to store the custom translations along the others in the yaml, but with a prefix. For example, we can imagine using tenant_%{id} as a prefix, so when looking for the key en.dashboard.index.title we will first try to look into en.tenant_%{id}.dashboard.index.title



We can achieve this by extending the default I18n backend so that it will first look for the translation in the custom scope, and return it if found. This can be done by overloading the translate method :




# config/initializers/i18n.rb
Rails.application.to_prepare do
class I18nTenantPrefix < I18n::Backend::Simple
def translate(locale, key, options = {})
return super unless Current.tenant.present?

tenant_key = "#{Current.tenant.id}_#{key}"
return super unless exists?(locale, tenant_key, options)

super(locale, tenant_key, options)
end
end
I18n.backend = I18nTenantPrefix.new
end






This is a quick and efficient way to customize keys for our different tenants. To manage the translations in the YML file, we can use a tool like YAMLFish to allow anyone in the team to work on those translations.






Solution 2: store custom keys in the database



If we want the custom keys to be instantly available after update, without needing to redeploy the app, we can store them in the database. We can achieve this thanks to a special I18n backend that we can chain with the default one.



Writing an i18n backend means implementing a class that inherits I18n::Backend::Base and implements missing methods to store translations from arbitrary data (usually in memory) and translate a given key. This can be tedious but thankfully the i18n lib provide us with a backend named I18n::Backend::KeyValue which accepts a store class for which we only have to define 2 methods :





  • Store#[key] that should return the translation for the given key


  • Store#keys that should return all possible keys that the backend can handle



Then we can chain the default simple backend with our custom one, to provide a fallback mechanism :




# config/initializers/i18n.rb
Rails.application.config.to_prepare do
class CurrentTenantTranslationsStore
def [](key)
Current.tenant&.custom_keys&.dig(key)&.to_json
end

def keys
Current.tenant&.custom_keys&.keys || []
end
end

I18n.backend = I18n::Backend::Chain.new(
I18n::Backend::KeyValue.new(CurrentTenantTranslationsStore.new),
I18n::Backend::Simple.new
)
end






This provides a very easy way to customize translations for each tenant.






Conclusion



I18n backends are a powerful way to "hack" into the way translations are fetched, allowing, in our case, to provide custom translations per tenant.

1. Sofort-Triage & Abwehrmaßnahmen

SOC Incident Playbook: Vulnerability Remediation & Verification
Syntax validiert (0 Fehler)
title: Detect Exploitation - Custom translations per tenant in a Rails app thanks to I18n backends
id: a16535a6-86f6-4161-93ea-679d5e4abe7e
status: experimental
description: Automatisch generierte SIEM-Erkennungsregel basierend auf CTI Intelligence
references:
  - https://tsecurity.de/
author: iShareStuff CTI Automated Detection Engine
date: 2026-09-26
logsource:
  category: network_connection
  product: any
detection:
  selection:
      CommandLine|contains:
        - 'exploit'
  condition: selection
falsepositives:
  - Legitime administrative Zugriffe oder Penetrationstests
level: high
tags:
  - attack.initial_access
Syntax validiert (0 Fehler)
rule CTI_Threat_Indicator {
    meta:
        author = "iShareStuff CTI Automated Detection Engine"
        date = "2026-09-26"
        description = "YARA Signature for "
    strings:
        $str = "Custom translations per tenant" ascii wide
    condition:
        any of them
}
Syntax validiert (0 Fehler)
index=security sourcetype IN ("cisco:asa", "pan:traffic", "zeek_conn", "suricata", "WinEventLog:Security")
("Custom translations per tenant in a Rail")
| stats count earliest(_time) as first_seen latest(_time) as last_seen by src_ip, dest_ip, dest_host, signature
| eval first_seen=strftime(first_seen, "%Y-%m-%d %H:%M:%S"), last_seen=strftime(last_seen, "%Y-%m-%d %H:%M:%S")
| sort - count
Syntax validiert (0 Fehler)
message: "*Custom translations per tenant in a Rail*"
Syntax validiert (0 Fehler)
CommonSecurityLog
| where Message has "Custom translations per tenant in a Rail"
| summarize EventCount = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by SourceIP, DestinationIP, DestinationPort, Activity
| extend DetectionRule = "iShareStuff-CTI-Compiled"
| sort by EventCount desc

2. Cyber Threat Intelligence & Forensik

🎯
MITRE ATT&CK Matrix Navigator 14 Taktiken
Reconnaissance
-
Resource Development
-
Initial Access
Execution
Persistence
-
Privilege Escalation
Defense Evasion
Credential Access
-
Discovery
-
Lateral Movement
-
Collection
-
Command and Control
Exfiltration
-
Impact
tsecurity.de Cognitive Threat RAG
Fokus-Vektor:

Kognitive Analyse für identifizierte Bedrohung: Erhöhte Bedrohungslage im Bereich Custom translations per tenant in a Rail.... Basierend auf 368k Vektor-Korrelationen werden sofortige Isolationsmaßnahmen für betroffene Endpunkte empfohlen.

🛡️ Angriffsfläche & Exposure

Netzwerk/Remote-Zugriff ohne Vorauthentifizierung möglich.

⚡ Empfohlene Sofortmaßnahmen
  • 1. Perimeter-Inspektion: Relevante Portfreigaben und exponierte Endpunkte unverzüglich scannen.
  • 2. Patch-Applikation: Hersteller-Hotfix einspielen oder betroffene Daemons in isolierte DMZ-Segmente überführen.
  • 3. Telemetrie & EDR-Alerts: Prozessaufrufe und Child-Processes auf anomale Shell-Spawns überwachen.
🔗 Semantisch verwandte Zero-Days MariaDB 11.7 VEC
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Custom translations per tenant in a Rails app thanks to I18n backends

Thematisch verwandte Begriffe: Custom, translations, tenant, Rails · 6 Treffer

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-88003 | InvoicePlane is a self-hosted open source application for managing invoi…
Advisory →
tsecurity.de Icon
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag