CARVIEW |
Select Language
HTTP/2 200
date: Sat, 23 Aug 2025 10:24:40 GMT
content-type: text/html; charset=utf-8
vary: X-PJAX, X-PJAX-Container, Turbo-Visit, Turbo-Frame, X-Requested-With,Accept-Encoding, Accept, X-Requested-With
x-robots-tag: none
etag: W/"32dfe08d8f740a922938a68556c4bd76"
cache-control: max-age=0, private, must-revalidate
strict-transport-security: max-age=31536000; includeSubdomains; preload
x-frame-options: deny
x-content-type-options: nosniff
x-xss-protection: 0
referrer-policy: no-referrer-when-downgrade
content-security-policy: default-src 'none'; base-uri 'self'; child-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/; connect-src 'self' uploads.github.com www.githubstatus.com collector.github.com raw.githubusercontent.com api.github.com github-cloud.s3.amazonaws.com github-production-repository-file-5c1aeb.s3.amazonaws.com github-production-upload-manifest-file-7fdce7.s3.amazonaws.com github-production-user-asset-6210df.s3.amazonaws.com *.rel.tunnels.api.visualstudio.com wss://*.rel.tunnels.api.visualstudio.com objects-origin.githubusercontent.com copilot-proxy.githubusercontent.com proxy.individual.githubcopilot.com proxy.business.githubcopilot.com proxy.enterprise.githubcopilot.com *.actions.githubusercontent.com wss://*.actions.githubusercontent.com productionresultssa0.blob.core.windows.net/ productionresultssa1.blob.core.windows.net/ productionresultssa2.blob.core.windows.net/ productionresultssa3.blob.core.windows.net/ productionresultssa4.blob.core.windows.net/ productionresultssa5.blob.core.windows.net/ productionresultssa6.blob.core.windows.net/ productionresultssa7.blob.core.windows.net/ productionresultssa8.blob.core.windows.net/ productionresultssa9.blob.core.windows.net/ productionresultssa10.blob.core.windows.net/ productionresultssa11.blob.core.windows.net/ productionresultssa12.blob.core.windows.net/ productionresultssa13.blob.core.windows.net/ productionresultssa14.blob.core.windows.net/ productionresultssa15.blob.core.windows.net/ productionresultssa16.blob.core.windows.net/ productionresultssa17.blob.core.windows.net/ productionresultssa18.blob.core.windows.net/ productionresultssa19.blob.core.windows.net/ github-production-repository-image-32fea6.s3.amazonaws.com github-production-release-asset-2e65be.s3.amazonaws.com insights.github.com wss://alive.github.com wss://alive-staging.github.com api.githubcopilot.com api.individual.githubcopilot.com api.business.githubcopilot.com api.enterprise.githubcopilot.com; font-src github.githubassets.com; form-action 'self' github.com gist.github.com copilot-workspace.githubnext.com objects-origin.githubusercontent.com; frame-ancestors 'none'; frame-src viewscreen.githubusercontent.com notebooks.githubusercontent.com; img-src 'self' data: blob: github.githubassets.com media.githubusercontent.com camo.githubusercontent.com identicons.github.com avatars.githubusercontent.com private-avatars.githubusercontent.com github-cloud.s3.amazonaws.com objects.githubusercontent.com release-assets.githubusercontent.com secured-user-images.githubusercontent.com/ user-images.githubusercontent.com/ private-user-images.githubusercontent.com opengraph.githubassets.com copilotprodattachments.blob.core.windows.net/github-production-copilot-attachments/ github-production-user-asset-6210df.s3.amazonaws.com customer-stories-feed.github.com spotlights-feed.github.com objects-origin.githubusercontent.com *.githubusercontent.com; manifest-src 'self'; media-src github.com user-images.githubusercontent.com/ secured-user-images.githubusercontent.com/ private-user-images.githubusercontent.com github-production-user-asset-6210df.s3.amazonaws.com gist.github.com; script-src github.githubassets.com; style-src 'unsafe-inline' github.githubassets.com; upgrade-insecure-requests; worker-src github.githubassets.com github.com/assets-cdn/worker/ github.com/assets/ gist.github.com/assets-cdn/worker/
server: github.com
content-encoding: gzip
accept-ranges: bytes
set-cookie: _gh_sess=xnGbYK31mqCmEkv6DC%2B4B4FKKpGiJHU3eDW%2FUSMvxdGH85%2FO5Gsp3rA%2FQhQqEjX7pNIJhv%2FAuYaGf%2BYHTC9vK0lt2SpIf1qJQJ%2FbTpp84gRYB9Zpd86BRw5yeGnVUqrZjIcRo8CcnEes8FKOhn9up1HP9fq%2FkMQHBWB%2Bp4UNFMziY9kgshAYuvWEu3UbqoIAa5SzA5SCv9nTgpZSRqMThxFO6mfU167fp54YqC6a5raHM7l7q6e9jUjcwXh5mCgGQtosg7%2Fxc2dq2SosYNsCeQ%3D%3D--P%2FXhA5yJy58AHfOe--76lU1nXGZcjYAnTlVlBSSQ%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax
set-cookie: _octo=GH1.1.808069363.1755944679; Path=/; Domain=github.com; Expires=Sun, 23 Aug 2026 10:24:39 GMT; Secure; SameSite=Lax
set-cookie: logged_in=no; Path=/; Domain=github.com; Expires=Sun, 23 Aug 2026 10:24:39 GMT; HttpOnly; Secure; SameSite=Lax
x-github-request-id: C14E:2F761D:47F8C7:5F1A4E:68A996E7
Custom CSV import and export tasks · glebm/i18n-tasks Wiki · GitHub
Skip to content
Navigation Menu
{{ message }}
-
Notifications
You must be signed in to change notification settings - Fork 273
Custom CSV import and export tasks
lorint edited this page Jan 10, 2020
·
10 revisions
These custom tasks for CSV import and export were originally posted by @lacco in https://github.com/glebm/i18n-tasks/pull/95.
The code below is also available as a gem: https://github.com/halostatue/i18n-tasks-csv.
The first column contains the key. The second column contains the value in the base locale. The subsequent columns contain the values in the other locales (one column per locale). The first row of the CSV is the header row.
Example:
key | en | de |
---|---|---|
app.greeting | Hello | Hallo |
app.farewell | Goodbye | Tschüss |
Add CSV configuration to config/i18n-tasks.yml
:
# config/i18n-tasks.yml
<% require './lib/i18n_csv_tasks' %>
csv:
export:
- ["faqs.*", "tmp/i18n-export/faqs.csv"]
- "tmp/i18n-export/main.csv"
import:
- tmp/i18n-export/main.csv
- tmp/i18n-export/faqs.csv
Put implementation in lib/i18n_csv_tasks.rb
:
# lib/i18n_csv_tasks.rb
require 'i18n/tasks/commands'
require 'csv'
module I18nCsvTasks
include ::I18n::Tasks::Command::Collection
cmd :csv_export, desc: 'export translations to CSV'
def csv_export(opts = {})
translations_by_path = {}
router = I18n::Tasks::Data::Router::PatternRouter.new(nil, write: i18n.config["csv"]["export"])
i18n.locales.each do |locale|
router.route(locale, i18n.data_forest) do |path, nodes|
translations_by_path[path] ||= {}
translations_by_path[path][locale] ||= {}
nodes.leaves do |node|
translations_by_path[path][locale][node.full_key(root: false)] = node.value
end
end
end
translations_by_path.each do |(path, translations_by_locale)|
FileUtils.mkdir_p(File.dirname(path))
CSV.open(path, "wb") do |csv|
csv << (["key"] + i18n.locales)
translations_by_locale[i18n.base_locale].keys.each do |key|
values = i18n.locales.map do |locale|
translations_by_locale[locale][key]
end
csv << values.unshift(key)
end
end
end
end
cmd :csv_import, desc: 'import translations from CSV'
def csv_import(opts = {})
i18n.config["csv"]["import"].each do |file|
csv = open(file).read.force_encoding('UTF-8')
translations = []
CSV.parse(csv, headers: true) do |row|
key = row["key"]
next unless key
i18n.locales.each do |locale|
raise "Locale missing for key #{key}! (locales in app: #{locales} / locales in file: #{row.headers.inspect})" unless row.has_key?(locale)
translations << [[locale, key].join("."), row[locale]]
end
end
# # Uncomment this in order to attempt to recognise entries that are likely symbols pointing to
# # other translations, intended to be rendered in your .yml with a preceding colon:
# translations.map! { |t| [t.first, (t.last&.=~ /^(?=.*\.)[a-z0-9_\.]+$/) ? t.last.to_sym : t.last] }
i18n.data.merge! I18n::Tasks::Data::Tree::Siblings.from_flat_pairs(translations)
end
end
end
I18n::Tasks.add_commands I18nCsvTasks
$ i18n-tasks csv-import
$ i18n-tasks csv-export
You can’t perform that action at this time.