diff options
Diffstat (limited to 'customising')
-rw-r--r-- | customising/config.md | 1137 | ||||
-rw-r--r-- | customising/index.md | 44 | ||||
-rw-r--r-- | customising/themes.md | 188 | ||||
-rw-r--r-- | customising/translation.md | 179 |
4 files changed, 1548 insertions, 0 deletions
diff --git a/customising/config.md b/customising/config.md new file mode 100644 index 000000000..dc9756181 --- /dev/null +++ b/customising/config.md @@ -0,0 +1,1137 @@ +--- +layout: page +title: Configuration +--- + +# Configuring Alaveteli + +<p class="lead"> + You can control much of how Alaveteli looks and behaves just by + changing the config settings. +</p> + +## The general configuration file + +The alaveteli code ships with an example configuration file: `config/general.yml-example`. + +As part of the [installation process]({{ site.baseurl }}installing ), the +example file gets copied to `config/general.yml`. You **must** edit this file to +suit your needs. + +Note that the default settings for frontpage examples are designed to work with +the dummy data shipped with Alaveteli. Once you have real data, you should +certainly edit these. + +Note that there are [other configuration files](#other-config) too, for specific aspects of Alaveteli. + + +## Config settings by topic + +The following are all the configuration settings that you can change in `config/general.yml`. +When you edit this file, remember it must be in the <a href="http://yaml.org">YAML syntax</a>. +It's not complicated but — especially if you're editing a list — be careful to get the +indentation correct. If in doubt, look at the examples already in the file, and don't use tabs. + + +### Appearance and overall behaviour of the site: + +<code><a href="#site_name">SITE_NAME</a></code> +<br> <code><a href="#domain">DOMAIN</a></code> +<br> <code><a href="#force_ssl">FORCE_SSL</a></code> +<br> <code><a href="#force_registration_on_new_request">FORCE_REGISTRATION_ON_NEW_REQUEST</a></code> +<br> <code><a href="#theme_urls">THEME_URLS</a></code> +<br> <code><a href="#theme_branch">THEME_BRANCH</a></code> +<br> <code><a href="#frontpage_publicbody_examples">FRONTPAGE_PUBLICBODY_EXAMPLES</a></code> +<br> <code><a href="#public_body_statistics_page">PUBLIC_BODY_STATISTICS_PAGE</a></code> +<br> <code><a href="#minimum_requests_for_statistics">MINIMUM_REQUESTS_FOR_STATISTICS</a></code> + +### Site status: + +<code><a href="#read_only">READ_ONLY</a></code> +<br> <code><a href="#staging_site">STAGING_SITE</a></code> + +### Locale and internationalisation: + +<code><a href="#iso_country_code">ISO_COUNTRY_CODE</a></code> +<br> <code><a href="#time_zone">TIME_ZONE</a></code> +<br> <code><a href="#available_locales">AVAILABLE_LOCALES</a></code> +<br> <code><a href="#default_locale">DEFAULT_LOCALE</a></code> +<br> <code><a href="#use_default_browser_language">USE_DEFAULT_BROWSER_LANGUAGE</a></code> +<br> <code><a href="#include_default_locale_in_urls">INCLUDE_DEFAULT_LOCALE_IN_URLS</a></code> + +### Definition of "late": + +<code><a href="#reply_late_after_days">REPLY_LATE_AFTER_DAYS</a></code> +<br> <code><a href="#reply_very_late_after_days">REPLY_VERY_LATE_AFTER_DAYS</a></code> +<br> <code><a href="#special_reply_very_late_after_days">SPECIAL_REPLY_VERY_LATE_AFTER_DAYS</a></code> +<br> <code><a href="#working_or_calendar_days">WORKING_OR_CALENDAR_DAYS</a></code> + +### Admin access: + +<code><a href="#admin_username">ADMIN_USERNAME</a></code> +<br> <code><a href="#admin_password">ADMIN_PASSWORD</a></code> +<br> <code><a href="#admin_username">DISABLE_EMERGENCY_USER</a></code> +<br> <code><a href="#skip_admin_auth">SKIP_ADMIN_AUTH</a></code> + +### Email management: + +<code><a href="#incoming_email_domain">INCOMING_EMAIL_DOMAIN</a></code> +<br> <code><a href="#incoming_email_prefix">INCOMING_EMAIL_PREFIX</a></code> +<br> <code><a href="#incoming_email_secret">INCOMING_EMAIL_SECRET</a></code> +<br> <code><a href="#blackhole_prefix">BLACKHOLE_PREFIX</a></code> +<br> <code><a href="#contact_email">CONTACT_EMAIL</a></code> +<br> <code><a href="#contact_name">CONTACT_NAME</a></code> +<br> <code><a href="#track_sender_email">TRACK_SENDER_EMAIL</a></code> +<br> <code><a href="#track_sender_name">TRACK_SENDER_NAME</a></code> +<br> <code><a href="#raw_emails_location">RAW_EMAILS_LOCATION</a></code> +<br> <code><a href="#exception_notifications_from">EXCEPTION_NOTIFICATIONS_FROM</a></code> +<br> <code><a href="#exception_notifications_to">EXCEPTION_NOTIFICATIONS_TO</a></code> +<br> <code><a href="#forward_nonbounce_responses_to">FORWARD_NONBOUNCE_RESPONSES_TO</a></code> +<br> <code><a href="#mta_log_path">MTA_LOG_PATH</a></code> +<br> <code><a href="#mta_log_type">MTA_LOG_TYPE</a></code> + +### General admin (keys, paths, back-end services): + +<code><a href="#cookie_store_session_secret">COOKIE_STORE_SESSION_SECRET</a></code> +<br> <code><a href="#recaptcha_public_key">RECAPTCHA_PUBLIC_KEY</a></code> +<br> <code><a href="#recaptcha_private_key">RECAPTCHA_PRIVATE_KEY</a></code> +<br> <code><a href="#gaze_url">GAZE_URL</a></code> +<br> <code><a href="#ga_code">GA_CODE</a></code> (GA=Google Analytics) +<br> <code><a href="#utility_search_path">UTILITY_SEARCH_PATH</a></code> +<br> <code><a href="#shared_files_path">SHARED_FILES_PATH</a></code> +<br> <code><a href="#shared_files">SHARED_FILES</a></code> +<br> <code><a href="#shared_directories">SHARED_DIRECTORIES</a></code> + +### Behaviour settings and switches: + +<code><a href="#new_response_reminder_after_days">NEW_RESPONSE_REMINDER_AFTER_DAYS</a></code> +<br> <code><a href="#max_requests_per_user_per_day">MAX_REQUESTS_PER_USER_PER_DAY</a></code> +<br> <code><a href="#override_all_public_body_request_emails">OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS</a></code> +<br> <code><a href="#allow_batch_requests">ALLOW_BATCH_REQUESTS</a></code> +<br> <code><a href="#public_body_list_fallback_to_default_locale">PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE</a></code> +<br> <code><a href="#cache_fragments">CACHE_FRAGMENTS</a></code> + +### External public services: + +<code><a href="#blog_feed">BLOG_FEED</a></code> +<br> <code><a href="#twitter_username">TWITTER_USERNAME</a></code> +<br> <code><a href="#twitter_widget_id">TWITTER_WIDGET_ID</a></code> +<br> <code><a href="#donation_url">DONATION_URL</a></code> + +### Development work or special cases: + +<code><a href="#debug_record_memory">DEBUG_RECORD_MEMORY</a></code> +<br> <code><a href="#varnish_host">VARNISH_HOST</a></code> +<br> <code><a href="#use_mailcatcher_in_development">USE_MAILCATCHER_IN_DEVELOPMENT</a></code> +<br> <code><a href="#use_ghostscript_compression">USE_GHOSTSCRIPT_COMPRESSION</a></code> +<br> <code><a href="#html_to_pdf_command">HTML_TO_PDF_COMMAND</a></code> + + +--- + +## All the general settings + + +<dl class="glossary"> + + <dt> + <a name="site_name"><code>SITE_NAME</code></a> + </dt> + <dd> + <strong>SITE_NAME</strong> appears in various places throughout the site. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>SITE_NAME: 'Alaveteli'</code> + </li> + <li> + <code>SITE_NAME: 'WhatDoTheyKnow'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="domain"><code>DOMAIN</code></a> + </dt> + <dd> + Domain used in URLs generated by scripts (e.g. for going in some emails) + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>DOMAIN: '127.0.0.1:3000'</code> + </li> + <li> + <code>DOMAIN: 'www.example.com'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="force_ssl"><code>FORCE_SSL</code></a> + </dt> + <dd> + If true forces everyone (in the production environment) to use encrypted connections + (via https) by redirecting unencrypted connections. This is <strong>highly + recommended</strong> so that logins can't be intercepted by naughty people. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>FORCE_SSL: true</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="iso_country_code"><code>ISO_COUNTRY_CODE</code></a> + </dt> + <dd> + The <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-2">ISO country code</a> + of the country in which your Alaveteli site is deployed. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>ISO_COUNTRY_CODE: GB</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="time_zone"><code>TIME_ZONE</code></a> + </dt> + <dd> + This is the <a href="http://en.wikipedia.org/wiki/List_of_tz_database_time_zones">timezone</a> + that Alaveteli usese to display times and dates. + If not set, defaults to UTC. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>TIME_ZONE: Australia/Sydney</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="blog_feed"><code>BLOG_FEED</code></a> + </dt> + <dd> + These feeds are displayed accordingly on the Alaveteli "blog" page: <!-- TODO --> + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>BLOG_FEED: 'http://www.mysociety.org/category/projects/whatdotheyknow/feed/'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="twitter_username"><code>TWITTER_USERNAME</code></a> + <a name="twitter_widget_id"><code>TWITTER_WIDGET_ID</code></a> + </dt> + <dd> + If you want a twitter feed displayed on the "blog" page, provide the widget ID and username. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>TWITTER_USERNAME: WhatDoTheyKnow</code> + </li> + <li> + <code>TWITTER_WIDGET_ID: '833549204689320031'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="available_locales"><code>AVAILABLE_LOCALES</code></a> & + <a name="default_locale"><code>DEFAULT_LOCALE</code></a> + </dt> + <dd> + <strong>AVAILABLE_LOCALES</strong> lists all the locales you want your site to support. + If there is more than one, use spaces betwween the entries. + Nominate one of these locales as the default with <strong>DEFAULT_LOCALE</strong>. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>AVAILABLE_LOCALES: 'en es'</code> + </li> + <li> + <code>DEFAULT_LOCALE: 'en'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="use_default_browser_language"><code>USE_DEFAULT_BROWSER_LANGUAGE</code></a> + </dt> + <dd> + Should Alaveteli try to use the default language of the user's browser? + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>USE_DEFAULT_BROWSER_LANGUAGE: true</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="include_default_locale_in_urls"><code>INCLUDE_DEFAULT_LOCALE_IN_URLS</code></a> + </dt> + <dd> + Normally, Alaveteli will put the locale into its URLs, like this + <code>www.example.com/en/body/list/all</code>. If you don't want this + behaviour whenever the locale is the default one, set + <strong>INCLUDE_DEFAULT_LOCALE_IN_URLS</strong> to false. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>INCLUDE_DEFAULT_LOCALE_IN_URLS: true</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="reply_late_after_days"><code>REPLY_LATE_AFTER_DAYS</code></a><br> + <a name="reply_very_late_after_days"><code>REPLY_VERY_LATE_AFTER_DAYS</code></a><br> + <a name="special_reply_very_late_after_days"><code>SPECIAL_REPLY_VERY_LATE_AFTER_DAYS</code></a> + <a name="working_or_calendar_days"><code>WORKING_OR_CALENDAR_DAYS</code></a> + </dt> + <dd> + The <strong>REPLY...AFTER_DAYS</strong> settings define how many days must have + passed before an answer to a request is officially <em>late</em>. + The SPECIAL case is for some types of authority (for example: in the UK, schools) which are + granted a bit longer than everyone else to respond to questions. + The <strong>WORKING_OR_CALENDAR_DAYS</strong> setting can be either "working" (the default) + or "calendar", and determines which days are counted. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>REPLY_LATE_AFTER_DAYS: 20</code> + </li> + <li> + <code>REPLY_VERY_LATE_AFTER_DAYS: 40</code> + </li> + <li> + <code>SPECIAL_REPLY_VERY_LATE_AFTER_DAYS: 60</code> + </li> + <li> + <code>WORKING_OR_CALENDAR_DAYS: working</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="frontpage_publicbody_examples"><code>FRONTPAGE_PUBLICBODY_EXAMPLES</code></a> + </dt> + <dd> + Specify which public bodies you want to be listed as examples on the home page, + using their <code>short_names</code>. + If you want more than one, separate them with semicolons. + Comment this out if you want this to be auto-generated. + <p> + <strong>Warning</strong>: this is slow — don't use in production! + </p> + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>FRONTPAGE_PUBLICBODY_EXAMPLES: 'tgq'</code> + </li> + <li> + <code>FRONTPAGE_PUBLICBODY_EXAMPLES: 'tgq;foo;bar'</code> + </li> + <li> + <code># FRONTPAGE_PUBLICBODY_EXAMPLES: </code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="theme_urls"><code>THEME_URLS</code></a> + </dt> + <dd> + URLs of <a href="{{ site.baseurl }}customising/themes">themes</a> to download and use + (when running the <code>rails-post-deploy</code> script). The earlier in the list means + the templates have a higher priority. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <pre> +THEME_URLS: + - 'git://github.com/mysociety/alavetelitheme.git' +</pre> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="theme_branch"><code>THEME_BRANCH</code></a> + </dt> + <dd> + When <code>rails-post-deploy</code> installs the <a href="{{ site.baseurl }}customising/themes">themes</a>, + it will try the theme branch first, but only if you've set <code>THEME_BRANCH</code> + to be true. If the branch doesn't exist it will fall back to using a tagged version + specific to your installed alaveteli version, and if that doesn't exist it will + back to <code>master</code>. + <p> + The default theme is the "Alaveteli" theme. This gets installed automatically when + <code>rails-post-deploy</code> runs. + </p> + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>THEME_BRANCH: false</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="force_registration_on_new_request"><code>FORCE_REGISTRATION_ON_NEW_REQUEST</code></a> + </dt> + <dd> + Does a user needs to sign in to start the New Request process? + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>FORCE_REGISTRATION_ON_NEW_REQUEST: false</code> + </li> + </ul> + </div> + </dd> + + + <dt> + <a name="incoming_email_domain"><code>INCOMING_EMAIL_DOMAIN</code></a> + </dt> + <dd> + Your email domain for incoming mail. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>INCOMING_EMAIL_DOMAIN: 'localhost'</code> + </li> + <li> + <code>INCOMING_EMAIL_DOMAIN: 'foifa.com'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="incoming_email_prefix"><code>INCOMING_EMAIL_PREFIX</code></a> + </dt> + <dd> + An optional prefix to help you distinguish FOI requests. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>INCOMING_EMAIL_PREFIX: ''</code> + </li> + <li> + <code>INCOMING_EMAIL_PREFIX: 'foi+'</code> + </li> + </ul> + </div> + </dd> + + + <dt> + <a name="incoming_email_secret"><code>INCOMING_EMAIL_SECRET</code></a> + </dt> + <dd> + Used for hash in request email address. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>INCOMING_EMAIL_SECRET: '11ae 4e3b 70ff c001 3682 4a51 e86d ef5f'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="blackhole_prefix"><code>BLACKHOLE_PREFIX</code></a> + </dt> + <dd> + Used as envelope from at the incoming email domain for cases where you don't care about failure. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>BLACKHOLE_PREFIX: 'do-not-reply-to-this-address'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="admin_username"><code>ADMIN_USERNAME</code></a> + & + <a name="admin_password"><code>ADMIN_PASSWORD</code></a> + <br> + <a name="admin_username"><code>DISABLE_EMERGENCY_USER</code></a> + </dt> + <dd> + The emergency user. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>ADMIN_USERNAME: 'adminxxxx'</code> + </li> + <li> + <code>ADMIN_PASSWORD: 'passwordx'</code> + </li> + <li> + <code>DISABLE_EMERGENCY_USER: false</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="skip_admin_auth"><code>SKIP_ADMIN_AUTH</code></a> + </dt> + <dd> + Set this to true, and the admin interface will be available to anonymous users. + Obviously, you should not set this to be true in production environments. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>SKIP_ADMIN_AUTH: false</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="contact_email"><code>CONTACT_EMAIL</code></a> + & + <a name="contact_name"><code>CONTACT_NAME</code></a> + </dt> + <dd> + Email "from" details. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>CONTACT_EMAIL: 'team@example.com'</code> + </li> + <li> + <code>CONTACT_NAME: 'Alaveteli Webmaster'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="track_sender_email"><code>TRACK_SENDER_EMAIL</code></a> & + <a name="track_sender_name"><code>TRACK_SENDER_NAME</code></a> + </dt> + <dd> + Email "from" details for track messages. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>TRACK_SENDER_EMAIL: 'alaveteli@example.com'</code> + </li> + <li> + <code>TRACK_SENDER_NAME: 'Alaveteli Webmaster'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="raw_emails_location"><code>RAW_EMAILS_LOCATION</code></a> + </dt> + <dd> + Where the raw incoming email data gets stored. + <strong>Make sure you back this up!</strong> + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>RAW_EMAILS_LOCATION: 'files/raw_emails'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="cookie_store_session_secret"><code>COOKIE_STORE_SESSION_SECRET</code></a> + </dt> + <dd> + Secret key for signing cookie_store sessions. Make it long and random. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>COOKIE_STORE_SESSION_SECRET: 'uIngVC238Jn9NsaQizMNf89pliYmDBFugPjHS2JJmzOp8'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="read_only"><code>READ_ONLY</code></a> + </dt> + <dd> + If present, <strong>READ_ONLY</strong> puts the site in read-only mode, + and uses the text as reason (whole paragraph). Please use a read-only database + user as well, as it only checks in a few obvious places. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + Typically, you do <strong>not</strong> want to run your site in + read-only mode — so set <strong>READ_ONLY</strong> to be + an empty string. + <br> + <code> + READ_ONLY: '' + </code> + </li> + <li> + <code> + READ_ONLY: 'The site is not currently accepting requests while we move the server.' + </code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="staging_site"><code>STAGING_SITE</code></a> + </dt> + <dd> + Is this a staging or development site (1) or a live (production) site (0)? + This controls whether or not the <code>rails-post-deploy</code> script + will create the file <code>config/rails_env.rb</code> file to force + Rails into production environment. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>STAGING_SITE: 1</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="recaptcha_public_key"><code>RECAPTCHA_PUBLIC_KEY</code></a> & + <a name="recaptcha_private_key"><code>RECAPTCHA_PRIVATE_KEY</code></a> + </dt> + <dd> + Recaptcha, for detecting humans. Get keys here: + <a href="http://recaptcha.net/whyrecaptcha.html">http://recaptcha.net/whyrecaptcha.html</a> + + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>RECAPTCHA_PUBLIC_KEY: '7HoPjGBBBBBBBBBkmj78HF9PjjaisQ893'</code> + </li> + <li> + <code>RECAPTCHA_PRIVATE_KEY: '7HjPjGBBBBBCBBBpuTy8a33sgnGG7A'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="new_response_reminder_after_days"><code>NEW_RESPONSE_REMINDER_AFTER_DAYS</code></a> + </dt> + <dd> + Number of days after which to send a 'new response reminder'. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>NEW_RESPONSE_REMINDER_AFTER_DAYS: [3, 10, 24]</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="debug_record_memory"><code>DEBUG_RECORD_MEMORY</code></a> + </dt> + <dd> + For debugging memory problems. If true, Alaveteli logs + the memory use increase of the Ruby process due to the + request (Linux only). Since Ruby never returns memory to the OS, if the + existing process previously served a larger request, this won't + show any consumption for the later request. + + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>DEBUG_RECORD_MEMORY: false</code> + </li> + </ul> + </div> + </dd> + + + <dt> + <a name="use_ghostscript_compression"><code>USE_GHOSTSCRIPT_COMPRESSION</code></a> + </dt> + <dd> + Currently we default to using pdftk to compress PDFs. You can + optionally try Ghostscript, which should do a better job of + compression. Some versions of pdftk are buggy with respect to + compression, in which case Alaveteli doesn't recompress the PDFs at + all and logs a warning message "Unable to compress PDF" — which would + be another reason to try this setting. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>USE_GHOSTSCRIPT_COMPRESSION: true</code> + </li> + </ul> + </div> + </dd> + + + <dt> + <a name="gaze_url"><code>GAZE_URL</code></a> + </dt> + <dd> + Alateveli uses mySociety's gazeteer service to determine country from incoming + IP address (this lets us suggest an Alaveteli in their country, if one exists). + You shouldn't normally need to change this. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>GAZE_URL: http://gaze.mysociety.org</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="forward_nonbounce_responses_to"><code>FORWARD_NONBOUNCE_RESPONSES_TO</code></a> + </dt> + <dd> + The email address to which non-bounce responses should be forwarded + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>FORWARD_NONBOUNCE_RESPONSES_TO: user-support@example.com</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="html_to_pdf_command"><code>HTML_TO_PDF_COMMAND</code></a> + </dt> + <dd> + Path to a program that converts an HTML page in a file to PDF. It + should take two arguments: the URL, and a path to an output file. + A static binary of <a href="http://wkhtmltopdf.org">wkhtmltopdf</a> is recommended. + If the command is not present, a text-only version will be rendered + instead. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>HTML_TO_PDF_COMMAND: /usr/local/bin/wkhtmltopdf-amd64</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="exception_notifications_from"><code>EXCEPTION_NOTIFICATIONS_FROM</code></a> & + <a name="exception_notifications_to"><code>EXCEPTION_NOTIFICATIONS_TO</code></a> + </dt> + <dd> + Email address(es) used for sending exception notifications. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <pre> +EXCEPTION_NOTIFICATIONS_FROM: do-not-reply-to-this-address@example.com + +EXCEPTION_NOTIFICATIONS_TO: + - robin@example.com + - seb@example.com +</pre> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="max_requests_per_user_per_day"><code>MAX_REQUESTS_PER_USER_PER_DAY</code></a> + </dt> + <dd> + This rate limiting can be turned off per-user via the admin interface. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>MAX_REQUESTS_PER_USER_PER_DAY: 6</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="varnish_host"><code>VARNISH_HOST</code></a> + </dt> + <dd> + If you're running behind Varnish, it might help to set this to + work out where to send purge requests. + Otherwise, don't set it. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>VARNISH_HOST: null</code> + </li> + <li> + <code>VARNISH_HOST: localhost</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="ga_code"><code>GA_CODE</code> (GA=Google Analytics)</a> + </dt> + <dd> + Adding a value here will enable Google Analytics on all non-admin pages for non-admin users. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>GA_CODE: ''</code> + </li> + <li> + <code>GA_CODE: 'AB-8222142-14'</code> + </li> + </ul> + </div> + </dd> + + + <dt> + <a name="override_all_public_body_request_emails"><code>OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS</code></a> + </dt> + <dd> + If you want to override <strong>all</strong> the public body request emails with + your own email address so that request emails that would normally go to the public body + go to you, use this setting. + This is useful for a staging server, so you can play with the whole process of sending requests + without inadvertently sending an email to a real authority. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <code>OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS: test-email@foo.com</code> + </li> + <li> + If you don't want this behaviour, comment the setting out + <br> + <code># OVERRIDE_ALL_PUBLIC_BODY_REQUEST_EMAILS:</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="utility_search_path"><code>UTILITY_SEARCH_PATH</code></a> + </dt> + <dd> + Search path for external command-line utilities (such as pdftohtml, pdftk, unrtf). + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>UTILITY_SEARCH_PATH: ["/usr/bin", "/usr/local/bin"]</code> + </li> + </ul> + </div> + </dd> + + + <dt> + <a name="mta_log_path"><code>MTA_LOG_PATH</code></a> + </dt> + <dd> + Path to your exim or postfix log files that will get sucked up + by <code>script/load-mail-server-logs</code>. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>MTA_LOG_PATH: '/var/log/exim4/exim-mainlog-*'</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="mta_log_type"><code>MTA_LOG_TYPE</code></a> + </dt> + <dd> + Are you using "exim" or "postfix" for your Mail Transfer Agnt (MTA)? + + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>MTA_LOG_TYPE: "exim"</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="donation_url"><code>DONATION_URL</code></a> + </dt> + <dd> + URL where people can donate to the organisation running the site. If set, + this will be included in the message people see when their request is + successful. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>DONATION_URL: "http://www.mysociety.org/donate/"</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="public_body_statistics_page"><code>PUBLIC_BODY_STATISTICS_PAGE</code></a> & + <a name="minimum_requests_for_statistics"><code>MINIMUM_REQUESTS_FOR_STATISTICS</code></a> + </dt> + <dd> + If <strong>PUBLIC_BODY_STATISTICS_PAGE</strong> is set to true, Alaveteli will make a + page of statistics on the performance of public bodies (which you can see at + <code>/body_statistics</code>). + The page will only consider public bodies that have had at least the number of requests + set by <strong>MINIMUM_REQUESTS_FOR_STATISTICS</strong>. + + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>PUBLIC_BODY_STATISTICS_PAGE: false</code> + </li> + <li> + <code>MINIMUM_REQUESTS_FOR_STATISTICS: 50</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="public_body_list_fallback_to_default_locale"><code>PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE</code></a> + </dt> + <dd> + If you would like the public body list page to include bodies that have no translation + in the current locale (but which do have a translation in the default locale), set this to true. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>PUBLIC_BODY_LIST_FALLBACK_TO_DEFAULT_LOCALE: false</code> + </li> + </ul> + </div> + </dd> + + + <dt> + <a name="use_mailcatcher_in_development"><code>USE_MAILCATCHER_IN_DEVELOPMENT</code></a> + </dt> + <dd> + <!-- TODO check mailcatcher URL --> + If true, while in development mode, try to send mail by SMTP to port + 1025 (the port the <a href="http://mailcatcher.me">mailcatcher</a> listens on by default): + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>USE_MAILCATCHER_IN_DEVELOPMENT: true</code> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="cache_fragments"><code>CACHE_FRAGMENTS</code></a> + </dt> + <dd> + Use memcached to cache HTML fragments for better performance. + This will only have an effect in environments where + <code>config.action_controller.perform_caching</code> is set to true + + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>CACHE_FRAGMENTS: true</code> + </li> + </ul> + </div> + </dd> + + + + <dt> + <a name="shared_files_path"><code>SHARED_FILES_PATH</code></a> + </dt> + <dd> + In some deployments of Alaveteli you may wish to install each newly + deployed version alongside the previous ones, in which case certain + files and resources should be shared between these installations. + For example, the <code>files</code> directory, the <code>cache</code> directory and the + generated graphs such as <code>public/foi-live-creation.png</code>. If you're + installing Alaveteli in such a setup then set <strong>SHARED_FILES_PATH</strong> to + the directory you're keeping these files under. Otherwise, leave it blank. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>SHARED_FILES_PATH: ''</code> <!-- TODO specific example --> + </li> + </ul> + </div> + </dd> + + + <dt> + <a name="shared_files"><code>SHARED_FILES</code></a> & + <a name="shared_directories"><code>SHARED_DIRECTORIES</code></a> + </dt> + <dd> + If you have <strong>SHARED_FILES_PATH</strong> set, then these options list the files + and directories that are shared; i.e. those to which the deploy scripts + should create symlinks from the repository. + <div class="more-info"> + <p>Examples:</p> + <ul> + <li> + <pre> +SHARED_FILES: + - config/database.yml + - config/general.yml + - config/rails_env.rb + - config/newrelic.yml + - config/httpd.conf + - public/foi-live-creation.png + - public/foi-user-use.png + - config/aliases + </pre> + </li> + <li> + <pre> +SHARED_DIRECTORIES: + - files/ + - cache/ + - lib/acts_as_xapian/xapiandbs/ + - vendor/bundle + - public/assets + </pre> + </li> + </ul> + </div> + </dd> + + <dt> + <a name="allow_batch_requests"><code>ALLOW_BATCH_REQUESTS</code></a> + </dt> + <dd> + Allow some users to make batch requests to multiple authorities. Once + this is set to true, you can enable batch requests for an individual + user via the user admin page. + <div class="more-info"> + <p>Example:</p> + <ul> + <li> + <code>ALLOW_BATCH_REQUESTS: false</code> + </li> + </ul> + </div> + </dd> + +</dl> + +<a name="other-config"> </a> + +## Other configuration files + +Note that there are other configuration files for Alaveteli — you'll find them all +in the `config` directory. These are presented in the git repository as `*-example` files +which you can copy into place. + +<dl> + <dt> + <strong>database.yml</strong> + </dt> + <dd> + database settings (as per Rails) + </dd> + <dt> + <strong>deploy.yml</strong> + </dt> + <dd> + deployment specifications used by Capistrano + </dd> + <dt> + <strong>httpd.conf, nginx.conf</strong> + </dt> + <dd> + Apache and Nginx configuration suggestions + </dd> + <dt> + <strong>newrelic.yml</strong> + </dt> + <dd> + Analytics configuration + </dd> +</dl>
\ No newline at end of file diff --git a/customising/index.md b/customising/index.md new file mode 100644 index 000000000..db1f5321f --- /dev/null +++ b/customising/index.md @@ -0,0 +1,44 @@ +--- +layout: page +title: Customising +--- + +# Customising Alaveteli + +<p class="lead"> + There are two ways to make your installation look and act the way you want. + Some behaviour can be controlled with <strong>configuration settings</strong>. + For more complex changes, you'll need to create a new <strong>theme</strong>. +</p> + + +## Configuration settings + +You can customise much of Alaveteli's behaviour just by editing the configuration +file. This [complete list of Alaveteli's config settings]({{ site.baseurl }}customising/config) +shows the sort of things you can control in this way. + +<!-- TODO key settings --> + +## Simple branding: colour and logo + +It's common to want to change the basic appearance of the site. Although you +can simply edit the default templates and CSS to do this, we **strongly +recommend** that you [create a theme]({{ site.baseurl }}customising/themes). + +Themes do not need to be especially complex, but they allow your changes to +work alongside the core code, which you can then update (when new releases or +updates become available). + +## Need Alaveteli in a different language? + +No problem! See the [information about translating Alaveteli]({{ site.baseurl }}customising/translation). + +## Complex changes + +If you are a developer (or you have a team of programmers available) you can +add any customisation that you want. But it's important to do this without +breaking the core code, so that you can accept new releases with updates. +There's more detail in the [page about themes]({{ site.baseurl }}customising/themes). + +See also the [documentation for developers]({{ site.baseurl }}developers). diff --git a/customising/themes.md b/customising/themes.md new file mode 100644 index 000000000..f6e504eff --- /dev/null +++ b/customising/themes.md @@ -0,0 +1,188 @@ +--- +layout: page +title: Themes +--- + +# Alaveteli's themes + +<p class="lead"> + Alaveteli uses <strong>themes</strong> to make the site look and run + differently from the default. + Simple changes like colour and logo are relatively easy, but themes can also + control more complex things like <em>how</em> the site behaves. +</p> + +When you customise your Alaveteli site, there is a lot you can change just +by editing the [config settings]({{ site.baseurl }}customising/config). +But if you want to change the way the site looks, or add more specific +behaviour, you'll need to make a **theme**. + +You don't need to be a programmer in order to make simple changes, but you will +need to be confident enough to copy and change some files. If you're not sure +about this, [ask for help](/community)! + +## What you might want to change + +The most common requirement is to brand the site: at a minimum, +inserting your own logo and colour scheme. You may also want to tweak +the different states that a request can go through. You'll also want +to edit the categories that public bodies can appear in (i.e. the +groupings on the left hand side of the +"[View authorities](http://www.whatdotheyknow.com/body/list/all)" page +on WhatDoTheyKnow. + +There may also be other things you want to customise -- drop a line on +the developer's mailing list to discuss what you need. We're still working +out the best way of doing these kinds of customisations! + +In any case, the important principle to bear in mind is that the less +you override and customise the code, the easier your site will be to +maintain in the long term. Any customisation is possible, but for +each customisation beyond the simple cases documented here, ask +yourself (or your client), "can we possibly live without this?" If the +answer is "no", then consider starting a discussion about a pluggable +way of achieving your goals, rather than overriding any of the core +code. + +## General principles + +We try to encapsulate all site-specific functionality in one of these +places: + +* Site [configuration]({{ site.baseurl }}customisation/config ) + (e.g., the name of your site, the available + languages, and so on — all in `config/general.yml`) +* Data (e.g. the public bodies to whom requests should be addressed) +* A theme, installed in `lib/themes`. + +This document is about what you can do in a theme. + +By default, the sample theme ("alavetelitheme") has already been +installed. See the setting +[`THEME_URLS`]({{ site.baseurl }}customising/config/#theme_urls) +in `general.yml` for an explanation. + +You can also install the sample theme by hand, by running: + + bundle exec rails plugin install git://github.com/mysociety/alavetelitheme.git + +The sample theme contains examples for nearly everything you might +want to customise. You should probably make a copy, rename it, and +use that as the basis for your own theme. + +## Make sure your theme is as lightweight as possible + +The more you put in your theme, the harder it will be to upgrade to +future versions of Alaveteli. Everything you place in your theme +overrides things in the core theme, so if you make a new "main +template", then new widgets that appear in the core theme won't appear +on your website. + +Therefore, you should consider how you can brand your website without +changing much in the core theme. The ideal would be if you are able +to rebrand the site by only changing the CSS. You will also need to +add custom help pages, as described below. + +## Branding the site + +The core templates that comprise the layout and user interface of an +Alaveteli site live in `app/views/`. They use Rails' ERB syntax. +For example, the template for the home page lives at +`app/views/general/frontpage.html.erb`, and the template for the "about +us" page is at `app/views/help/about.html.erb`. + +Obviously, you *could* edit those core files directly, but this would +be a Bad Idea, because you would find it increasingly hard to do +upgrades. Having said that, sometimes you may want to change the core +templates in a way that would benefit everyone, in which case, discuss +the changes on the mailing list, make them in a fork of Alaveteli, and +then issue a pull request. + +Normally, however, you should override these pages **in your own +theme**, by placing them at a corresponding location within your +theme's `lib/` directory. These means that a file at +`lib/themes/alavetelitheme/lib/help/about.rhml` will appear +instead of the core "about us" file. + +Rails expects all its stylesheets to live at `<railshome>/public`, +which presents a problem for plugins. Here's how we solve it: the +stylesheet and associated resources for your theme live (by +convention) in `alavetelitheme/public/`. This is symlinked from +the main Rails app -- see `alavetelitheme/install.rb` to see how this +happens. + +The partial at +`alavetelitheme/lib/views/general/_before_head_end.html.erb` includes the +custom CSS in your theme's stylesheet folder (by convention, in +`alavetelitheme/public/stylesheets/`), with: + + <%= stylesheet_link_tag "/alavetelitheme/stylesheets/custom" %> + +...which will, usually, need changing for your theme. + +## Adding your own categories for public bodies + +Categories are implemented in Alaveteli using tags. Specific tags can +be designated to group authorities together as a category. + +There's a file in the sample theme, +`alavetelitheme/lib/public_body_categories_en.rb`, which contains a +nested structure that defines categories. It contains a comment +describing its structure. You should make a copy of this file for each +locale you support. + +## Customising the request states + +As mentioned above, if you can possibly live with the +[default Alaveteli request statuses]({{ site.baseurl }}running/states), +it would be good to do so. Note that you can set how many days counts +as "overdue" in the main site config file — +see [`REPLY_LATE_AFTER_DAYS`]({{ site.baseurl }}customising/config/#reply_late_after_days). + +If you can't live with the states as they are, there's a very basic +way to add to them (which will get improved over time). There's not +currently a way to remove any easily. There is an example of how to +do this in the `alavetelitheme`. + +To do add states, create two modules in your theme, +`InfoRequestCustomStates` and `RequestControllerCustomStates`. The +former must have these methods: + +* `theme_calculate_status`: return a tag to identify the current state of the request +* `theme_extra_states`: return a list of tags which identify the extra states you'd like to support +* `theme_display_status`: return human-readable strings corresponding with these tags + +The latter must have one method: + +* `theme_describe_state`: Return a notice for the user suitable for + displaying after they've categorised a request; and redirect them to + a suitable next page + +When you've added your extra states, you also need to create the following files in your theme: + +* `lib/views/general/_custom_state_descriptions.html.erb`: Descriptions + of your new states, suitable for displaying to end users +* `lib/views/general/_custom_state_transitions_complete.html.erb`: + Descriptions for any new states that you might characterise as + 'completion' states, for displaying on the categorisation form that + we ask requestors to fill out +* `lib/views/general/_custom_state_transitions_pending.html.erb`: As + above, but for new states you might characterise as 'pending' + states. + +You can see examples of these customisations in +[this commit](https://github.com/sebbacon/informatazyrtare-theme/commit/2b240491237bd72415990399904361ce9bfa431d) +for the Kosovan version of Alaveteli, Informata Zyrtare (ignore the +file `lib/views/general/_custom_state_transitions.html.erb`, which is +unused). + +## Adding new pages in the navigation + +`alavetelitheme/lib/config/custom-routes.rb` allows you to extend the base routes in +Alaveteli. The example in `alavetelitheme` adds an extra help page. +You can also use this to override the behaviour of specific pages if +necessary. + +## Adding or overriding models and controllers + +If you need to extend the behaviour of Alaveteli at the controller or model level, see `alavetelitheme/lib/controller_patches.rb` and `alavetelitheme/lib/model_patches.rb` for examples.
\ No newline at end of file diff --git a/customising/translation.md b/customising/translation.md new file mode 100644 index 000000000..927067f89 --- /dev/null +++ b/customising/translation.md @@ -0,0 +1,179 @@ +--- +layout: page +title: Translation +--- + +# Translating Alaveteli + +<p class="lead"> + We've designed Alaveteli to be used in many different + jurisdictions all around the world. If it doesn't already + support the language you need, you can help by translating + it. This page explains how. +</p> + +## Alaveteli's translations + +The software translations are implemented using GNU gettext, and the resource +files are managed in Transifex. + +The Transifex project is at +[https://www.transifex.net/projects/p/alaveteli](https://www.transifex.net/proje +cts/p/alaveteli) -- you'll probably want an account there (ask on the mailing +list). It has a fairly easy-to-use interface for contributing translations. + +There are three roles in the translation process, and each one is described +below: **translator**, **developer**, and **release manager**. You probably only +need to know about the one that applies to you. + +## Translation process: translator's view + +**If you're just working on translating Alavetli into a language you know, then +this section is for you.** + +When a developer adds a new feature to the user interface in Alaveteli, they +use some code to mark sentences or words ("strings") that they think will need +to be translated. + +When the Alaveteli release manager is planning a release, they will upload a +template containing all the strings to be translated (called a POT) to +Transifex. This causes your own translations in Transifex to be updated with +the latest strings. + +When you visit Transifex, it will prompt you to fill out values for all new +strings, and all strings that have been modified. In the case where a string +has only been slightly modified, such as with punctuation ("Hello" has become +"Hello!"), Transifex will suggest a suitable translation for you (look for the +"suggestions" tab under the source string). + +In order for this feature to work properly, the release manager has to download +your translations, run a program that inserts the suggestions, and then upload +them again. Therefore, when a release candidate is announced, make sure you +have uploaded any outstanding translations, or you will lose them. + +When a release candidate has been annouced, there is a **translation freeze**: +during this period, developers must not add any new strings to the software, so +you can be confident that you're translating everything that will be in the +final release. + +The release manager will also give you a **translation deadline**. After this +date, you can continue to contribute new translations, but they won't make it +into the release. + +### General notes on translation in Transifex + +Some strings will have comments attached to them from the Alaveteli +application developers about the context in which the text appears in the +application — these comments will appear under the 'Details' tab for the text +in Transifex. + +Some strings will have **placeholders** in them to indicate that Alaveteli +will insert some text of its own into them when they're displayed. They +will be surrounded by double curly brackets, and look like this: + +<code> + some text with {{placeholder}} in it +</code> + +For these strings, don't translate the placeholder. It needs to stay exactly +the same for the text to be inserted properly: + +<code> + ein Text mit {{placeholder}} in ihm +</code> + +Similarly, some strings may contain small bits of HTML — these will have +code in angle brackets (it might really be indicating that the text is a link, +or that it needs special formatting). For example: + +<code> + please <a href=\"{{url}}\">send it to us</a> +</code> + +Again, don't edit the bits between the angle brackets — preserve them in your +translation, and just edit the text around them. So the example might become: + +<code> + bitte <a href=\"{{url}}\">schicken Sie es uns</a> +</code> + +Some strings are in the form of two pieces of text separated by a vertical +bar (`|`) character, e.g. `IncomingMessage|Subject`. These represent attribute +names, so `IncomingMessage|Subject` is the subject attribute of an incoming +message on the site. Do not prioritise these types of text when translating -- +they do not appear on the site anywhere at the moment, and when they do, they +will only be used in the admin interface. If you do translate them, only +translate the text that comes *after* the `|`. + +## Translation process: developers' view + +**If you're writing new code for Alaveteli, then you're a developer, and you +need to understand how to make any text you add easy for translators to work +with.** + +Please read our [internationalisation +guide](http://mysociety.github.io/internationalization.html) for our advice on +using strings that will need translation. This applies across all mySociety +projects, not just Alaveteli. + +The release manager will enforce a translation freeze just before a new release +is cut. During such time, you must not introduce new strings to the code if +your work is due for inclusion in this release. This is necessary to allow +translators time to complete and check their translations against all the known +strings. + +## Translation process: release manager's view + +**If you're responsible for coordinating translators and developers so that all +the work comes together in a new release, you're the release manager.** + +This is the most complicated of the three roles -- the chances are this doesn't +apply to you, so only read it if you want to understand how the process works. + +As the release manager, before you cut a new release branch, you must do the +following: + +### Before the release candidate date: + +* Pick a date for the release branch to be cut ("release candidate date"). +* Make an announcement to the translators (using the "announcements" + feature in Transifex) that they should ensure they have any pending + translations saved in Transifex before the release candidate date. +* Make an announcement to the developers that all new strings should + be committed before the release candidate date. + +### On the release candidate date: + +* Download all the current translations with `tx pull -a -f` and commit (important: there's no revision history in Transifex!). +* You should also commit these translations to a hotfix for the + previous version, so they are preserved against the last known + good msgids. +* Regenerate the POT file and individual PO files for each language, + using `bundle exec rake gettext:store_model_attributes`, followed by + `bundle exec rake gettext:find` + * Be careful not to include msgids from themes in `lib/themes`; + you might want to move them out of the way before running + the above commands. + * This updates the PO template, but also merges it with the + individual PO files, marking strings that have only changed + slightly as "fuzzy". +* Re-upload the POT and PO files to Transifex from the + current release branch with `tx push -s -t` + * The point of uploading the PO files is that Transifex + converts the "fuzzy" suggestions from Transifex into + "suggestions" under each source string. + * Note that Transifex *does not* preserve fuzzy strings in the + PO files it makes available for download, on the grounds + that Transifex supports multiple suggestions, whereas + gettext only allows one fuzzy suggestion per msgid. +* Remove the fuzzy strings from the local PO files (because they + make Rails very noisy), and then commit the result. You can do + this by re-pulling from Transifex. + +### On the release date: + +* Download and commit all the current translations to the current release branch. + + + + |