Added Site Setting to change locale.

This commit is contained in:
Robin Ward 2013-02-28 14:31:39 -05:00
parent e37c7f1e1d
commit 628927a79f
23 changed files with 640 additions and 97 deletions

View File

@ -21,7 +21,7 @@ gem 'fastimage'
gem 'fog', require: false
gem 'has_ip_address'
gem 'hiredis'
gem 'i18n-js'
# note: for image_optim to correctly work you need
# sudo apt-get install -y advancecomp gifsicle jpegoptim libjpeg-progs optipng pngcrush
gem 'image_optim'

View File

@ -203,8 +203,6 @@ GEM
hiredis (0.4.5)
httpauth (0.2.0)
i18n (0.6.1)
i18n-js (2.1.2)
i18n
image_optim (0.7.2)
fspath (~> 2.0.3)
image_size (~> 1.1)
@ -479,7 +477,6 @@ DEPENDENCIES
guard-spork
has_ip_address
hiredis
i18n-js
image_optim
jasminerice
jquery-rails

View File

@ -20,11 +20,6 @@
// The rest of the externals
//= require_tree ./external
//= require i18n
// The following needs to go right after including i18n, because other scripts
// below require correctly set locale already
//= require init_locale
//= require ./discourse/helpers/i18n_helpers
//= require ./discourse

View File

@ -1 +0,0 @@
I18n.locale = window.currentLocale;

View File

@ -1,2 +1,3 @@
//= depend_on 'client.en.yml'
<%= JsLocaleHelper.output_locale(:en); %>
//= require locales/i18n
<%= JsLocaleHelper.output_locale(:en) %>

View File

@ -1,2 +1,3 @@
//= depend_on 'client.fr.yml'
<%= JsLocaleHelper.output_locale(:fr); %>
//= require locales/i18n
<%= JsLocaleHelper.output_locale(:fr) %>

View File

@ -0,0 +1,531 @@
// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
if (!Array.prototype.indexOf) {
Array.prototype.indexOf = function(searchElement /*, fromIndex */) {
"use strict";
if (this === void 0 || this === null) {
throw new TypeError();
}
var t = Object(this);
var len = t.length >>> 0;
if (len === 0) {
return -1;
}
var n = 0;
if (arguments.length > 0) {
n = Number(arguments[1]);
if (n !== n) { // shortcut for verifying if it's NaN
n = 0;
} else if (n !== 0 && n !== (Infinity) && n !== -(Infinity)) {
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
}
if (n >= len) {
return -1;
}
var k = n >= 0
? n
: Math.max(len - Math.abs(n), 0);
for (; k < len; k++) {
if (k in t && t[k] === searchElement) {
return k;
}
}
return -1;
};
}
// Instantiate the object
var I18n = I18n || {};
// Set default locale to english
I18n.defaultLocale = "en";
// Set default handling of translation fallbacks to false
I18n.fallbacks = false;
// Set default separator
I18n.defaultSeparator = ".";
// Set current locale to null
I18n.locale = null;
// Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.
I18n.PLACEHOLDER = /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm;
I18n.fallbackRules = {
};
I18n.pluralizationRules = {
en: function (n) {
return n == 0 ? ["zero", "none", "other"] : n == 1 ? "one" : "other";
}
};
I18n.getFallbacks = function(locale) {
if (locale === I18n.defaultLocale) {
return [];
} else if (!I18n.fallbackRules[locale]) {
var rules = []
, components = locale.split("-");
for (var l = 1; l < components.length; l++) {
rules.push(components.slice(0, l).join("-"));
}
rules.push(I18n.defaultLocale);
I18n.fallbackRules[locale] = rules;
}
return I18n.fallbackRules[locale];
}
I18n.isValidNode = function(obj, node, undefined) {
return obj[node] !== null && obj[node] !== undefined;
};
I18n.lookup = function(scope, options) {
var options = options || {}
, lookupInitialScope = scope
, translations = this.prepareOptions(I18n.translations)
, locale = options.locale || I18n.currentLocale()
, messages = translations[locale] || {}
, options = this.prepareOptions(options)
, currentScope
;
if (typeof(scope) == "object") {
scope = scope.join(this.defaultSeparator);
}
if (options.scope) {
scope = options.scope.toString() + this.defaultSeparator + scope;
}
scope = scope.split(this.defaultSeparator);
while (messages && scope.length > 0) {
currentScope = scope.shift();
messages = messages[currentScope];
}
if (!messages) {
if (I18n.fallbacks) {
var fallbacks = this.getFallbacks(locale);
for (var fallback = 0; fallback < fallbacks.length; fallbacks++) {
messages = I18n.lookup(lookupInitialScope, this.prepareOptions({locale: fallbacks[fallback]}, options));
if (messages) {
break;
}
}
}
if (!messages && this.isValidNode(options, "defaultValue")) {
messages = options.defaultValue;
}
}
return messages;
};
// Merge serveral hash options, checking if value is set before
// overwriting any value. The precedence is from left to right.
//
// I18n.prepareOptions({name: "John Doe"}, {name: "Mary Doe", role: "user"});
// #=> {name: "John Doe", role: "user"}
//
I18n.prepareOptions = function() {
var options = {}
, opts
, count = arguments.length
;
for (var i = 0; i < count; i++) {
opts = arguments[i];
if (!opts) {
continue;
}
for (var key in opts) {
if (!this.isValidNode(options, key)) {
options[key] = opts[key];
}
}
}
return options;
};
I18n.interpolate = function(message, options) {
options = this.prepareOptions(options);
var matches = message.match(this.PLACEHOLDER)
, placeholder
, value
, name
;
if (!matches) {
return message;
}
for (var i = 0; placeholder = matches[i]; i++) {
name = placeholder.replace(this.PLACEHOLDER, "$1");
value = options[name];
if (!this.isValidNode(options, name)) {
value = "[missing " + placeholder + " value]";
}
regex = new RegExp(placeholder.replace(/\{/gm, "\\{").replace(/\}/gm, "\\}"));
message = message.replace(regex, value);
}
return message;
};
I18n.translate = function(scope, options) {
options = this.prepareOptions(options);
var translation = this.lookup(scope, options);
try {
if (typeof(translation) == "object") {
if (typeof(options.count) == "number") {
return this.pluralize(options.count, scope, options);
} else {
return translation;
}
} else {
return this.interpolate(translation, options);
}
} catch(err) {
return this.missingTranslation(scope);
}
};
I18n.localize = function(scope, value) {
switch (scope) {
case "currency":
return this.toCurrency(value);
case "number":
scope = this.lookup("number.format");
return this.toNumber(value, scope);
case "percentage":
return this.toPercentage(value);
default:
if (scope.match(/^(date|time)/)) {
return this.toTime(scope, value);
} else {
return value.toString();
}
}
};
I18n.parseDate = function(date) {
var matches, convertedDate;
// we have a date, so just return it.
if (typeof(date) == "object") {
return date;
};
// it matches the following formats:
// yyyy-mm-dd
// yyyy-mm-dd[ T]hh:mm::ss
// yyyy-mm-dd[ T]hh:mm::ss
// yyyy-mm-dd[ T]hh:mm::ssZ
// yyyy-mm-dd[ T]hh:mm::ss+0000
//
matches = date.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2}))?(Z|\+0000)?/);
if (matches) {
for (var i = 1; i <= 6; i++) {
matches[i] = parseInt(matches[i], 10) || 0;
}
// month starts on 0
matches[2] -= 1;
if (matches[7]) {
convertedDate = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]));
} else {
convertedDate = new Date(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6]);
}
} else if (typeof(date) == "number") {
// UNIX timestamp
convertedDate = new Date();
convertedDate.setTime(date);
} else if (date.match(/\d+ \d+:\d+:\d+ [+-]\d+ \d+/)) {
// a valid javascript format with timezone info
convertedDate = new Date();
convertedDate.setTime(Date.parse(date))
} else {
// an arbitrary javascript string
convertedDate = new Date();
convertedDate.setTime(Date.parse(date));
}
return convertedDate;
};
I18n.toTime = function(scope, d) {
var date = this.parseDate(d)
, format = this.lookup(scope)
;
if (date.toString().match(/invalid/i)) {
return date.toString();
}
if (!format) {
return date.toString();
}
return this.strftime(date, format);
};
I18n.strftime = function(date, format) {
var options = this.lookup("date");
if (!options) {
return date.toString();
}
options.meridian = options.meridian || ["AM", "PM"];
var weekDay = date.getDay()
, day = date.getDate()
, year = date.getFullYear()
, month = date.getMonth() + 1
, hour = date.getHours()
, hour12 = hour
, meridian = hour > 11 ? 1 : 0
, secs = date.getSeconds()
, mins = date.getMinutes()
, offset = date.getTimezoneOffset()
, absOffsetHours = Math.floor(Math.abs(offset / 60))
, absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60)
, timezoneoffset = (offset > 0 ? "-" : "+") + (absOffsetHours.toString().length < 2 ? "0" + absOffsetHours : absOffsetHours) + (absOffsetMinutes.toString().length < 2 ? "0" + absOffsetMinutes : absOffsetMinutes)
;
if (hour12 > 12) {
hour12 = hour12 - 12;
} else if (hour12 === 0) {
hour12 = 12;
}
var padding = function(n) {
var s = "0" + n.toString();
return s.substr(s.length - 2);
};
var f = format;
f = f.replace("%a", options.abbr_day_names[weekDay]);
f = f.replace("%A", options.day_names[weekDay]);
f = f.replace("%b", options.abbr_month_names[month]);
f = f.replace("%B", options.month_names[month]);
f = f.replace("%d", padding(day));
f = f.replace("%e", day);
f = f.replace("%-d", day);
f = f.replace("%H", padding(hour));
f = f.replace("%-H", hour);
f = f.replace("%I", padding(hour12));
f = f.replace("%-I", hour12);
f = f.replace("%m", padding(month));
f = f.replace("%-m", month);
f = f.replace("%M", padding(mins));
f = f.replace("%-M", mins);
f = f.replace("%p", options.meridian[meridian]);
f = f.replace("%S", padding(secs));
f = f.replace("%-S", secs);
f = f.replace("%w", weekDay);
f = f.replace("%y", padding(year));
f = f.replace("%-y", padding(year).replace(/^0+/, ""));
f = f.replace("%Y", year);
f = f.replace("%z", timezoneoffset);
return f;
};
I18n.toNumber = function(number, options) {
options = this.prepareOptions(
options,
this.lookup("number.format"),
{precision: 3, separator: ".", delimiter: ",", strip_insignificant_zeros: false}
);
var negative = number < 0
, string = Math.abs(number).toFixed(options.precision).toString()
, parts = string.split(".")
, precision
, buffer = []
, formattedNumber
;
number = parts[0];
precision = parts[1];
while (number.length > 0) {
buffer.unshift(number.substr(Math.max(0, number.length - 3), 3));
number = number.substr(0, number.length -3);
}
formattedNumber = buffer.join(options.delimiter);
if (options.precision > 0) {
formattedNumber += options.separator + parts[1];
}
if (negative) {
formattedNumber = "-" + formattedNumber;
}
if (options.strip_insignificant_zeros) {
var regex = {
separator: new RegExp(options.separator.replace(/\./, "\\.") + "$")
, zeros: /0+$/
};
formattedNumber = formattedNumber
.replace(regex.zeros, "")
.replace(regex.separator, "")
;
}
return formattedNumber;
};
I18n.toCurrency = function(number, options) {
options = this.prepareOptions(
options,
this.lookup("number.currency.format"),
this.lookup("number.format"),
{unit: "$", precision: 2, format: "%u%n", delimiter: ",", separator: "."}
);
number = this.toNumber(number, options);
number = options.format
.replace("%u", options.unit)
.replace("%n", number)
;
return number;
};
I18n.toHumanSize = function(number, options) {
var kb = 1024
, size = number
, iterations = 0
, unit
, precision
;
while (size >= kb && iterations < 4) {
size = size / kb;
iterations += 1;
}
if (iterations === 0) {
unit = this.t("number.human.storage_units.units.byte", {count: size});
precision = 0;
} else {
unit = this.t("number.human.storage_units.units." + [null, "kb", "mb", "gb", "tb"][iterations]);
precision = (size - Math.floor(size) === 0) ? 0 : 1;
}
options = this.prepareOptions(
options,
{precision: precision, format: "%n%u", delimiter: ""}
);
number = this.toNumber(size, options);
number = options.format
.replace("%u", unit)
.replace("%n", number)
;
return number;
};
I18n.toPercentage = function(number, options) {
options = this.prepareOptions(
options,
this.lookup("number.percentage.format"),
this.lookup("number.format"),
{precision: 3, separator: ".", delimiter: ""}
);
number = this.toNumber(number, options);
return number + "%";
};
I18n.pluralizer = function(locale) {
pluralizer = this.pluralizationRules[locale];
if (pluralizer !== undefined) return pluralizer;
return this.pluralizationRules["en"];
};
I18n.findAndTranslateValidNode = function(keys, translation) {
for (i = 0; i < keys.length; i++) {
key = keys[i];
if (this.isValidNode(translation, key)) return translation[key];
}
return null;
};
I18n.pluralize = function(count, scope, options) {
var translation;
try {
translation = this.lookup(scope, options);
} catch (error) {}
if (!translation) {
return this.missingTranslation(scope);
}
var message;
options = this.prepareOptions(options);
options.count = count.toString();
pluralizer = this.pluralizer(this.currentLocale());
key = pluralizer(Math.abs(count));
keys = ((typeof key == "object") && (key instanceof Array)) ? key : [key];
message = this.findAndTranslateValidNode(keys, translation);
if (message == null) message = this.missingTranslation(scope, keys[0]);
return this.interpolate(message, options);
};
I18n.missingTranslation = function() {
var message = '[missing "' + this.currentLocale()
, count = arguments.length
;
for (var i = 0; i < count; i++) {
message += "." + arguments[i];
}
message += '" translation]';
return message;
};
I18n.currentLocale = function() {
return (I18n.locale || I18n.defaultLocale);
};
// shortcuts
I18n.t = I18n.translate;
I18n.l = I18n.localize;
I18n.p = I18n.pluralize;

View File

@ -1,2 +1,3 @@
//= depend_on 'client.nl.yml'
<%= JsLocaleHelper.output_locale(:nl); %>
//= require locales/i18n
<%= JsLocaleHelper.output_locale(:nl) %>

View File

@ -1,2 +1,3 @@
//= depend_on 'client.pseudo.yml'
<%= JsLocaleHelper.output_locale(:pseudo); %>
//= require locales/i18n
<%= JsLocaleHelper.output_locale(:pseudo) %>

View File

@ -0,0 +1,3 @@
//= depend_on 'client.sv.yml'
//= require locales/i18n
<%= JsLocaleHelper.output_locale(:sv) %>

View File

@ -21,6 +21,7 @@ class ApplicationController < ActionController::Base
before_filter :store_incoming_links
before_filter :preload_json
before_filter :check_xhr
before_filter :set_locale
rescue_from Exception do |exception|
unless [ ActiveRecord::RecordNotFound, ActionController::RoutingError,
@ -77,6 +78,11 @@ class ApplicationController < ActionController::Base
render file: 'public/403', formats: [:html], layout: false, status: 403
end
def set_locale
I18n.locale = SiteSetting.default_locale
end
def store_preloaded(key, json)
@preloaded ||= {}
# I dislike that there is a gsub as opposed to a gsub!

View File

@ -2,20 +2,22 @@ module JsLocaleHelper
def self.output_locale(locale)
SimplesIdeias::I18n.assert_usable_configuration!
locale_str = locale.to_s
s = "var I18n = I18n || {};"
segment = "app/assets/javascripts/i18n/#{locale}.js"
s += "I18n.translations = " + SimplesIdeias::I18n.translation_segments[segment].to_json + ";"
translations = YAML::load(File.open("#{Rails.root}/config/locales/client.#{locale_str}.yml"))
segment = "app/assets/javascripts/i18n/admin.#{locale}.js"
admin = SimplesIdeias::I18n.translation_segments[segment]
admin[locale][:js] = admin[locale].delete(:admin_js)
# We used to split the admin versus the client side, but it's much simpler to just
# include both for now due to the small size of the admin section.
#
# For now, let's leave it split out in the translation file in case we want to split
# it again later, so we'll merge the JSON ourselves.
admin_contents = translations[locale_str].delete('admin_js')
s += "jQuery.extend(true, I18n.translations, " + admin.to_json + ");"
s
translations[locale_str]['js'].merge!(admin_contents) if admin_contents.present?
result = "I18n.translations = #{translations.to_json};\n"
result << "I18n.locale = '#{locale_str}'\n"
result
end
end

View File

@ -149,6 +149,9 @@ class SiteSetting < ActiveRecord::Base
setting(:title_fancy_entities, true)
# The default locale for the site
setting(:default_locale, 'en')
client_setting(:educate_until_posts, 2)
def self.call_discourse_hub?

View File

@ -16,10 +16,6 @@
<%# load the selected locale before any other scripts %>
<%= javascript_include_tag "locales/#{I18n.locale}" %>
<%# store the locale into a variable, because the scripts need it, see init_locale.js %>
<script>
window.currentLocale = "<%= I18n.locale %>";
</script>
<%- if mini_profiler_enabled? %>
<%- Rack::MiniProfiler.step "application" do %>

View File

@ -34,6 +34,11 @@ module Discourse
'jquery.js', 'defer/html-sanitizer-bundle.js'
]
# Precompile all available locales
Dir.glob("app/assets/javascripts/locales/*.js.erb").each do |file|
config.assets.precompile << file.match(/([a-z]+\.js)\.erb$/)[1]
end
# Activate observers that should always be running.
config.active_record.observers = [
:user_email_observer,

View File

@ -1,38 +0,0 @@
# Split context in several files.
# By default only one file with all translations is exported and
# no configuration is required. Your settings for asset pipeline
# are automatically recognized.
#
# If you want to split translations into several files or specify
# locale contexts that will be exported, just use this file to do
# so.
#
# If you're going to use the Rails 3.1 asset pipeline, change
# the following configuration to something like this:
#
# translations:
# - file: "app/assets/javascripts/i18n/translations.js"
#
# If you're running an old version, you can use something
# like this:
#
# translations:
# - file: "public/javascripts/translations.js"
# only: "*"
#
translations:
- file: 'app/assets/javascripts/i18n/en.js'
only: 'en.js.*'
- file: 'app/assets/javascripts/i18n/admin.en.js'
only: 'en.admin_js.*'
- file: 'app/assets/javascripts/i18n/pseudo.js'
only: 'pseudo.js.*'
- file: 'app/assets/javascripts/i18n/admin.pseudo.js'
only: 'pseudo.admin_js.*'
- file: 'app/assets/javascripts/i18n/fr.js'
only: 'fr.js.*'
- file: 'app/assets/javascripts/i18n/admin.fr.js'
only: 'fr.admin_js.*'

View File

@ -15,6 +15,7 @@ exclude_paths:
- app/assets/javascripts/external/*
- app/assets/javascripts/external_production/*
- app/assets/javascripts/defer/*
- app/assets/javascripts/locales/i18n.js
# ------------ jshint options ------------

View File

@ -241,6 +241,10 @@ pseudo:
title: ! '[[ Łóǧ Íɳ ŵíťĥ Ýáĥóó ]]'
message: ! '[[ Áůťĥéɳťíčáťíɳǧ ŵíťĥ Ýáĥóó (ɱáǩé šůřé ƿóƿ ůƿ ƀłóčǩéřš ářé ɳóť
éɳáƀłéď) ]]'
github:
title: ! '[[ Łóǧ Íɳ ŵíťĥ Ǧíťĥůƀ ]]'
message: ! '[[ Áůťĥéɳťíčáťíɳǧ ŵíťĥ Ǧíťĥůƀ (ɱáǩé šůřé ƿóƿ ůƿ ƀłóčǩéřš ářé ɳóť
éɳáƀłéď) ]]'
composer:
saving_draft_tip: ! '[[ šáνíɳǧ ]]'
saved_draft_tip: ! '[[ šáνéď ]]'
@ -353,7 +357,9 @@ pseudo:
unread_posts: ! '[[ ýóů ĥáνé {{unread}} ůɳřéáď ółď ƿóšťš íɳ ťĥíš ťóƿíč ]]'
new_posts: ! '[[ ťĥéřé ářé {{new_posts}} ɳéŵ ƿóšťš íɳ ťĥíš ťóƿíč šíɳčé ýóů łášť
řéáď íť ]]'
likes: ! '[[ ťĥéřé ářé {{likes}} łíǩéš íɳ ťĥíš ťóƿíč ]]'
likes:
one: ! '[[ ťĥéřé íš 1 łíǩé íɳ ťĥíš ťóƿíč ]]'
other: ! '[[ ťĥéřé ářé {{count}} łíǩéš íɳ ťĥíš ťóƿíč ]]'
back_to_list: ! '[[ Ɓáčǩ ťó Ťóƿíč Łíšť ]]'
options: ! '[[ Ťóƿíč Óƿťíóɳš ]]'
show_links: ! '[[ šĥóŵ łíɳǩš ŵíťĥíɳ ťĥíš ťóƿíč ]]'

View File

@ -237,6 +237,7 @@ en:
yaxis: "Visits"
site_settings:
default_locale: "The default language of this Discourse instance (ISO 639-1 Code)"
min_post_length: "Minimum post length in characters"
max_post_length: "Maximum post length in characters"
min_topic_title_length: "Minimum topic title length in characters"

View File

@ -2,6 +2,7 @@
pseudo:
title: ! '[[ Ďíščóůřšé ]]'
topics: ! '[[ Ťóƿíčš ]]'
via: ! '[[ %{username} νíá %{site_name} ]]'
is_reserved: ! '[[ íš řéšéřνéď ]]'
too_many_mentions: ! '[[ ĥáš ťóó ɱáɳý ůšéřš ɱéɳťíóɳéď ]]'
too_many_images: ! '[[ ĥáš ťóó ɱáɳý íɱáǧéš ]]'
@ -225,7 +226,14 @@ pseudo:
action: ! '[[ Řé-Šůƀščříƀé ]]'
title: ! '[[ Řé-Šůƀščříƀéď! ]]'
description: ! '[[ Ýóů ĥáνé ƀééɳ řé-šůƀščříƀéď. ]]'
reports:
visits:
title: ! '[[ Ůšéřš Ѷíšíťš ƀý Ďáý ]]'
xaxis: ! '[[ Ďáý ]]'
yaxis: ! '[[ Ѷíšíťš ]]'
site_settings:
default_locale: ! '[[ Ťĥé ďéƒáůłť łáɳǧůáǧé óƒ ťĥíš Ďíščóůřšé íɳšťáɳčé (ÍŠÓ 639-1
Čóďé) ]]'
min_post_length: ! '[[ Ϻíɳíɱůɱ ƿóšť łéɳǧťĥ íɳ čĥářáčťéřš ]]'
max_post_length: ! '[[ Ϻáхíɱůɱ ƿóšť łéɳǧťĥ íɳ čĥářáčťéřš ]]'
min_topic_title_length: ! '[[ Ϻíɳíɱůɱ ťóƿíč ťíťłé łéɳǧťĥ íɳ čĥářáčťéřš ]]'
@ -239,7 +247,13 @@ pseudo:
ɳíčǩɳáɱé řéǧíšťřý áť ďíščóůřšé.óřǧ ]]'
educate_until_posts: ! '[[ Šĥóŵ ƿóƿ-ůƿ čóɱƿóšéř éďůčáťíóɳ ƿáɳéł ůɳťíł ťĥé ůšéř
ĥáš ɱáďé ťĥíš ɱáɳý ƿóšťš ]]'
title: ! '[[ Ťíťłé óƒ ťĥíš ŵéƀšíťé ]]'
title: ! '[[ Ťíťłé óƒ ťĥíš šíťé, ŵíłł ƀé ůšéď íɳ ťĥé ťíťłé ťáǧ áɳď éłšéŵĥéřé ]]'
company_full_name: ! '[[ Ťĥé ƒůłł ɳáɱé óƒ ťĥé čóɱƿáɳý ťĥáť řůɳš ťĥíš šíťé, ůšéď
íɳ łéǧáł ďóčůɱéɳťš łíǩé ťĥé /ťóš ]]'
company_short_name: ! '[[ Ťĥé šĥóřť ɳáɱé óƒ ťĥé čóɱƿáɳý ťĥáť řůɳš ťĥíš šíťé, ůšéď
íɳ łéǧáł ďóčůɱéɳťš łíǩé ťĥé /ťóš ]]'
company_domain: ! '[[ Ťĥé ďóɱáíɳ ɳáɱé óŵɳéď ƀý ťĥé čóɱƿáɳý ťĥáť řůɳš ťĥíš šíťé,
ůšéď íɳ łéǧáł ďóčůɱéɳťš łíǩé ťĥé /ťóš ]]'
restrict_access: ! '[[ Řéšťříčť ƒóřůɱ áččéšš ůɳłéšš á ƿáššŵóřď íš éɳťéřéď ]]'
access_password: ! '[[ Ŵĥéɳ řéšťříčťéď áččéšš íš éɳáƀłéď, ťĥíš ƿáššŵóřď ɱůšť ƀé
éɳťéřéď ]]'
@ -328,23 +342,35 @@ pseudo:
řóƀóťš.ťхť) ]]'
email_domains_blacklist: ! '[[ Á ƿíƿé-ďéłíɱíťéď łíšť óƒ éɱáíł ďóɱáíɳš ťĥáť ářé
ɳóť áłłóŵéď. Éхáɱƿłé: ɱáíłíɳáťóř.čóɱ|ťřášĥɱáíł.ɳéť ]]'
version_checks: ! '[[ Рíɳǧ Ďíščóůřšé Ĥůƀ ƒóř νéřšíóɳ ůƿďáťéš áɳď řéƿóřť ťĥéɱ óɳ
ťĥé áďɱíɳ ďášĥƀóářď. ]]'
port: ! '[[ ̓ ýóů''ď łíǩé ťó šƿéčíƒý á ƿóřť íɳ ťĥé ŮŘŁ. Ůšéƒůł íɳ ďéνéłóƿɱéɳť
ɱóďé. Łéáνé ƀłáɳǩ ƒóř ɳóɳé ]]'
force_hostname: ! '[[ ̓ ýóů''ď łíǩé ťó šƿéčíƒý á ĥóšťɳáɱé íɳ ťĥé ŮŘŁ. Ůšéƒůł
íɳ ďéνéłóƿɱéɳť ɱóďé. Łéáνé ƀłáɳǩ ƒóř ɳóɳé ]]'
version_checks: ! '[[ Рíɳǧ ťĥé Ďíščóůřšé Ĥůƀ ƒóř νéřšíóɳ ůƿďáťéš áɳď šĥóŵ νéřšíóɳ
ɱéššáǧéš óɳ ťĥé /áďɱíɳ ďášĥƀóářď ]]'
port: ! '[[ Ůšé ťĥíš ĤŤŤР ƿóřť řáťĥéř ťĥáɳ ťĥé ďéƒáůłť óƒ ƿóřť 80. Łéáνé ƀłáɳǩ
ƒóř ɳóɳé, ɱáíɳłý ůšéƒůł ƒóř ďéνéłóƿɱéɳť ]]'
force_hostname: ! '[[ Šƿéčíƒý á ĥóšťɳáɱé íɳ ťĥé ŮŘŁ. Łéáνé ƀłáɳǩ ƒóř ɳóɳé, ɱáíɳłý
ůšéƒůł ƒóř ďéνéłóƿɱéɳť ]]'
invite_expiry_days: ! '[[ Ĥóŵ łóɳǧ ůšéř íɳνíťáťíóɳ ǩéýš ářé νáłíď, íɳ ďáýš ]]'
enable_google_logins: ! '[[ Éɳáƀłé Ǧóóǧłé áůťĥéɳťíčáťíóɳ ]]'
enable_yahoo_logins: ! '[[ Éɳáƀłé Ýáĥóó áůťĥéɳťíčáťíóɳ ]]'
enable_twitter_logins: ! '[[ Éɳáƀłé Ťŵíťťéř áůťĥéɳťíčáťíóɳ, řéƣůířéš ťŵíťťéř_čóɳšůɱéř_ǩéý
áɳď ťŵíťťéř_čóɳšůɱéř_šéčřéť ]]'
twitter_consumer_key: ! '[[ Čóɳšůɱéř ǩéý ƒóř Ťŵíťťéř áůťĥéɳťíčáťíóɳ, řéǧíšťéřéď
áť ĥťťƿ://ďéν.ťŵíťťéř.čóɱ ]]'
twitter_consumer_secret: ! '[[ Čóɳšůɱéř šéčřéť ƒóř Ťŵíťťéř áůťĥéɳťíčáťíóɳ, řéǧíšťéřéď
áť ĥťťƿ://ďéν.ťŵíťťéř.čóɱ ]]'
enable_facebook_logins: ! '[[ Éɳáƀłé Ƒáčéƀóóǩ áůťĥéɳťíčáťíóɳ, řéƣůířéš ƒáčéƀóóǩ_áƿƿ_íď
áɳď ƒáčéƀóóǩ_áƿƿ_šéčřéť ]]'
facebook_app_id: ! '[[ Áƿƿ íď ƒóř Ƒáčéƀóóǩ áůťĥéɳťíčáťíóɳ, řéǧíšťéřéď áť ĥťťƿš://ďéνéłóƿéřš.ƒáčéƀóóǩ.čóɱ/áƿƿš
]]'
facebook_app_secret: ! '[[ Áƿƿ šéčřéť ƒóř Ƒáčéƀóóǩ áůťĥéɳťíčáťíóɳ, řéǧíšťéřéď
áť ĥťťƿš://ďéνéłóƿéřš.ƒáčéƀóóǩ.čóɱ/áƿƿš ]]'
enable_github_logins: ! '[[ Éɳáƀłé Ǧíťĥůƀ áůťĥéɳťíčáťíóɳ, řéƣůířéš ǧíťĥůƀ_čłíéɳť_íď
áɳď ǧíťĥůƀ_čłíéɳť_šéčřéť ]]'
github_client_id: ! '[[ Čłíéɳť íď ƒóř Ǧíťĥůƀ áůťĥéɳťíčáťíóɳ, řéǧíšťéřéď áť ĥťťƿš://ǧíťĥůƀ.čóɱ/šéťťíɳǧš/áƿƿłíčáťíóɳš
]]'
github_client_secret: ! '[[ Čłíéɳť šéčřéť ƒóř Ǧíťĥůƀ áůťĥéɳťíčáťíóɳ, řéǧíšťéřéď
áť ĥťťƿš://ǧíťĥůƀ.čóɱ/šéťťíɳǧš/áƿƿłíčáťíóɳš ]]'
allow_import: ! '[[ Áłłóŵ íɱƿóřť, ŵĥíčĥ čáɳ řéƿłáčé ÁŁŁ šíťé ďáťá; łéáνé ƒáłšé
ůɳłéšš ýóů ƿłáɳ ťó ďó íɱƿóřťš ]]'
ůɳłéšš ýóů ƿłáɳ ťó ďó ďáťá íɱƿóřťš ]]'
active_user_rate_limit_secs: ! '[[ Ĥóŵ ƒřéƣůéɳťłý ŵé ůƿďáťé ťĥé ''łášť_šééɳ_áť''
ƒíéłď, íɳ šéčóɳďš ]]'
previous_visit_timeout_hours: ! '[[ Ĥóŵ łóɳǧ á νíšíť łášťš ƀéƒóřé ŵé čóɳšíďéř
@ -357,21 +383,20 @@ pseudo:
ýóů čáɳ čřéáťé áɳóťĥéř ťóƿíč ]]'
rate_limit_create_post: ! '[[ Ĥóŵ ɱáɳý šéčóɳďš, áƒťéř čřéáťíɳǧ á ƿóšť, ƀéƒóřé
ýóů čáɳ čřéáťé áɳóťĥéř ƿóšť ]]'
max_likes_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ łíǩéš á ůšéř čáɳ ƿéřƒóřɱ íɳ á ďáý ]]'
max_flags_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ ƒłáǧš á ůšéř čáɳ ƿéřƒóřɱ íɳ á ďáý ]]'
max_bookmarks_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ ƀóóǩɱářǩš á ůšéř čáɳ čřéáťé íɳ
á ďáý ]]'
max_edits_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ éďíťš á ůšéř čáɳ ƿéřƒóřɱ íɳ á ďáý ]]'
max_favorites_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ ťóƿíčš ťĥáť čáɳ ƀé ƒáνóříťéď íɳ
á ďáý ]]'
max_topics_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ ťóƿíčš á ůšéř čáɳ čřéáťé íɳ á ďáý
]]'
max_private_messages_per_day: ! '[[ Ťĥé ɱáхíɱůɱ áɱóůɳť óƒ ƿříνáťé ɱéššáǧéš ýóů
čáɳ šéɳď íɳ á ďáý ]]'
suggested_topics: ! '[[ Ťĥé ɳůɱƀéř óƒ šůǧǧéšťéď ťóƿíčš áť ťĥé ƀóťťóɱ óƒ á ťóƿíč
]]'
max_likes_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ łíǩéš ƿéř ůšéř ƿéř ďáý ]]'
max_flags_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ ƒłáǧš ƿéř ůšéř ƿéř ďáý ]]'
max_bookmarks_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ ƀóóǩɱářǩš ƿéř ůšéř ƿéř ďáý ]]'
max_edits_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ éďíťš ƿéř ůšéř ƿéř ďáý ]]'
max_favorites_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ ťóƿíčš ťĥáť čáɳ ƀé ƒáνóříťéď ƿéř
ůšéř ƿéř ďáý ]]'
max_topics_per_day: ! '[[ Ϻáхíɱůɱ ɳůɱƀéř óƒ ťóƿíčš á ůšéř čáɳ čřéáťé ƿéř ďáý ]]'
max_private_messages_per_day: ! '[[ Ťĥé ɱáхíɱůɱ áɱóůɳť óƒ ƿříνáťé ɱéššáǧéš ůšéřš
čáɳ čřéáťé ƿéř ďáý ]]'
suggested_topics: ! '[[ Ťĥé ɳůɱƀéř óƒ šůǧǧéšťéď ťóƿíčš šĥóŵɳ áť ťĥé ƀóťťóɱ óƒ
á ťóƿíč ]]'
enable_s3_uploads: ! '[[ Рłáčé ůƿłóáďš óɳ Áɱážóɳ Š3 ]]'
s3_upload_bucket: ! '[[ Ťĥé Áɱážóɳ Š3 ƀůčǩéť ƒíłéš ŵíłł ƀé ůƿłóáďéď íɳťó ]]'
s3_upload_bucket: ! '[[ Ťĥé Áɱážóɳ Š3 ƀůčǩéť ɳáɱé ťĥáť ƒíłéš ŵíłł ƀé ůƿłóáďéď
íɳťó ]]'
default_invitee_trust_level: ! '[[ Ďéƒáůłť ťřůšť łéνéł (0-5) ƒóř íɳνíťéď ůšéřš
]]'
default_trust_level: ! '[[ Ďéƒáůłť ťřůšť łéνéł (0-5) ƒóř ůšéřš ]]'
@ -389,8 +414,10 @@ pseudo:
šéčóɳďš ]]'
max_word_length: ! '[[ Ťĥé ɱáхíɱůɱ áłłóŵéď ŵóřď łéɳǧťĥ, íɳ čĥářáčťéřš, íɳ á ťóƿíč
ťíťłé ]]'
title_min_entropy: ! '[[ Ťĥé ɱíɳíɱůɱ áłłóŵéď éɳťřóƿý ƒóř á ťóƿíč ťíťłé ]]'
body_min_entropy: ! '[[ Ťĥé ɱíɳíɱůɱ áłłóŵéď éɳťřóƿý ƒóř ƿóšť ƀóďý ]]'
title_min_entropy: ! '[[ Ťĥé ɱíɳíɱůɱ áłłóŵéď éɳťřóƿý (ůɳíƣůé čĥářáčťéřš) řéƣůířéď
ƒóř á ťóƿíč ťíťłé ]]'
body_min_entropy: ! '[[ Ťĥé ɱíɳíɱůɱ áłłóŵéď éɳťřóƿý (ůɳíƣůé čĥářáčťéřš) řéƣůířéď
ƒóř á ƿóšť ƀóďý ]]'
new_user_period_days: ! '[[ Ĥóŵ łóɳǧ á ůšéř íš ĥíǧĥłíǧĥťéď áš ƀéíɳǧ ɳéŵ, íɳ ďáýš
]]'
title_fancy_entities: ! '[[ Čóɳνéřť ƒáɳčý ĤŤϺŁ éɳťíťíéš íɳ ťóƿíč ťíťłéš ]]'
@ -629,6 +656,11 @@ pseudo:
]]'
text_body_template: ! "[[ %{username} ɱéɳťíóɳéď ýóů íɳ '%{topic_title}' óɳ %{site_name}:\n\n---\n%{message}\n\n---\nРłéášé
νíšíť ťĥíš łíɳǩ ťó řéšƿóɳď: %{base_url}%{url}\n ]]"
user_posted:
subject_template: ! '[[ [%{site_name}] %{username} ƿóšťéď íɳ ''%{topic_title}''
]]'
text_body_template: ! "[[ %{username} ƿóšťéď íɳ '%{topic_title}' óɳ %{site_name}:\n\n---\n%{message}\n\n---\nРłéášé
νíšíť ťĥíš łíɳǩ ťó řéšƿóɳď: %{base_url}%{url}\n ]]"
digest:
why: ! '[[ Ĥéřé''š á ƀříéƒ šůɱɱářý óƒ ŵĥáť ĥáƿƿéɳéď óɳ %{site_link} šíɳčé ŵé
łášť šáŵ ýóů óɳ %{last_seen_at}. ]]'

View File

@ -17,7 +17,6 @@
// The rest of the externals
//= require_tree ../../app/assets/javascripts/external
//= require i18n
//= require ../../app/assets/javascripts/discourse/helpers/i18n_helpers
//= require ../../app/assets/javascripts/discourse

View File

@ -3,7 +3,8 @@
[
{
"path": "app",
"folder_exclude_patterns": ["external", "external_production", "images", "imported", "fonts", "defer"]
"folder_exclude_patterns": ["external", "external_production", "images", "imported", "fonts", "defer"],
"file_exclude_patterns": ["i18n.js"]
},
{ "path": "config" },
{