Nous sommes un restaurant situé à Paris . Ceci est notre menu.
Nous sommes un restaurant situé à Paris . Ceci est notre menu.
Cliquez ici pour aller à l'entrée du site. ``` ### Disabling Url Relativizing _New in 1.4.0_ If you dont want a href attribute to be relativized (such as for making [a language switcher](https://github.com/untra/polyglot/blob/master/site/_includes/sidebar.html#L40)), you can use the block tag: ```html {% static_href %}href="..."{% endstatic_href %} ``` ```html click this static link ``` that will generate `click this static link` which is what you would normally use to create a url unmangled by invisible language relativization. Combine with a [html minifier](https://github.com/digitalsparky/jekyll-minifier) for a polished and production ready website. ### Exclusive site language generation _New in 1.4.0_ If you want to control which languages a document can be generated for, you can specify `lang-exclusive: [ ]` frontmatter. If you include this frontmatter in your post, it will only generate for the specified site languages. For Example, the following frontmatter will only generate in the `en` and `fr` site language builds: ``` --- lang-exclusive: ['en', 'fr'] --- ``` ### Localized site.data There are cases where you may want to have a list of `key: value` pairs of translated content. For example, instead of creating a complete separate file for each language containing the layout structure and localized content, you can create a single file with the layout that will be shared among pages, and then create a language-specific file with the localized content that will be used. To do this, you can create a file like `_data/:lang/strings.yml`, one for each language, and Polyglot will bring those keys under `site.data[:lang].strings`. For example, suppose you have the following files: `_data/en/strings.yml` ```yaml hello: "Hello" greetings: morning: "Good morning" evening: "Good evening" ``` `_data/pt-br/strings.yml` ```yaml hello: "Olá" greetings: morning: "Bom dia" evening: "Boa noite" ``` You can use the `site.data` to access the localized content in your layouts and pages: ```liquid
{{ site.data[site.active_lang].strings.hello }}, {{ site.data[site.active_lang].strings.greetings.morning }}
``` For more information on this matter, check out this [post](https://polyglot.untra.io/2024/02/29/localized-variables/). ### Localized collections To localize collections, you first have to properly define the collection in your `_config.yml` file. For example, if you have a collection of `projects`, you can define it like this: ```yaml collections: projects: output: true permalink: /:collection/:title/ ``` Note that the [permalink](https://jekyllrb.com/docs/permalinks/#collections) definition here is important. Then, you can create a file for each language in the `_projects` directory, and Polyglot will bring those files under `site.projects`. For more information, check the related discussion #188. ## How It Works This plugin makes modifications to existing Jekyll classes and modules, namely `Jekyll::StaticFile` and `Jekyll::Site`. These changes are as lightweight and slim as possible. The biggest change is in `Jekyll::Site.process`. Polyglot overwrites this method to instead spawn a separate process for each language you intend to process the site for. Each of those processes calls the original `Jekyll::Site.process` method with its language in mind, ensuring your website scales to support any number of languages, while building all of your site languages simultaneously. `Jekyll::Site.process` is the entry point for the Jekyll build process. Take care whatever other plugins you use do not also attempt to overwrite this method. You may have problems. ### (:polyglot, :post_write) hook _New in 1.8.0_ Polyglot issues a `:polyglot, :post_write` hook event once all languages have been built for the site. This hook runs exactly once, after all site languages been processed: ```rb Jekyll::Hooks.register :polyglot, :post_write do |site| # do something custom and cool here! end ``` ### Machine-aware site building _New in 1.5.0_ Polyglot will only start builds after it confirms there is a cpu core ready to accept the build thread. This ensures that jekyll will build large sites efficiently, streamlining build processes instead of overloading machines with process thrash. ### Writing Tests and Debugging _:wave: I need assistance with modern ruby best practices for test maintenance with rake and rspec. If you got the advice I have the ears._ Tests are run with `bundle exec rake`. Tests are in the `/spec` directory, and test failure output detail can be examined in the `rspec.xml` file. ## Features This plugin stands out from other I18n Jekyll plugins. - automatically corrects your relative links, keeping your *french* visitors on your *french* website, even when content has to fallback to the `default_lang`. - builds all versions of your website *simultaneously*, allowing big websites to scale efficiently. - provides the liquid tag `{{ site.languages }}` to get an array of your I18n strings. - provides the liquid tag `{{ site.default_lang }}` to get the default_lang I18n string. - provides the liquid tag `{{ site.active_lang }}` to get the I18n language string the website was built for. Alternative names for `active_lang` can be configured via `config.lang_vars`. - provides the liquid tag `{{ I18n_Headers }}` to append SEO bonuses to your website. - provides the liquid tag `{{ Unrelativized_Link href="/hello" }}` to make urls that do not get influenced by url correction regexes. - provides `site.data` localization for efficient rich text replacement. - a creator that will answer all of your questions and issues. ## SEO Recipes Jekyll-polyglot has a few spectacular [Search Engine Optimization techniques](https://untra.github.io/polyglot/seo) to ensure your Jekyll blog gets the most out of its multilingual audience. Check them out! ### Sitemap generation See the example [sitemap.xml](/site/sitemap.xml) and [robots.txt](/site/robots.txt) for how to automatically generate a multi-language sitemap for your page and turn it in for the SEO i18n credit. The [official Sitemap protocol documentation](https://www.sitemaps.org/protocol.html#location) states: > "The location of a Sitemap file determines the set of URLs that can be included in that Sitemap. A Sitemap file located at http://example.com/catalog/sitemap.xml can include any URLs starting with http://example.com/catalog/ but can not include URLs starting with http://example.com/images/." > "It is strongly recommended that you place your Sitemap at the root directory of your web server." To comply with this, 'sitemap.xml' should be added to the 'exclude_from_localization' list to ensure that only one `sitemap.xml` file exists in the root directory, rather than creating separate ones for each language. ## Compatibility Currently supports Jekyll 3.0 , and Jekyll 4.0 * Windows users will need to disable parallel_localization on their machines by setting `parallel_localization: false` in the `_config.yml` * In Jekyll 4.0 , SCSS source maps will generate improperly due to how Polyglot operates. The workaround is to disable the CSS sourcemaps. Adding the following to your `config.yml` will disable sourcemap generation: ```yaml sass: sourcemap: never ``` ## Contributions Please! I need all the support I can get! 🙏 But for real I would appreciate any code contributions and support. This started as an open-source side-project and has gotten bigger than I'd ever imagine! If you have something you'd like to contribute to jekyll-polyglot, please open a PR! ### Contributors These are talented and considerate software developers across the world that have lent their support to this project. **Thank You! ¡Gracias! Merci! Danke! 감사합니다! תודה רבה! Спасибо! Dankjewel! 谢谢!Obrigado!** * [@yunseo-kim](https://github.com/yunseo-kim) [improved i18n sitemaps]((https://polyglot.untra.io/2025/01/18/polyglot-1.9.0/)) * [@blackpill](https://github.com/blackpill) [1.8.1](https://polyglot.untra.io/2024/08/18/polyglot-1.8.1/) * [@hacketiwack](https://github.com/hacketiwack) [1.8.1](https://polyglot.untra.io/2024/08/18/polyglot-1.8.1/) * [@jerturowetz](https://github.com/jerturowetz) [sitemap generation](https://polyglot.untra.io/2024/03/17/polyglot-1.8.0/) * [@antoniovazquezblanco](https://github.com/antoniovazquezblanco) [1.7.0](https://polyglot.untra.io/2023/10/29/polyglot-1.7.0/) * [@salinatedcoffee](https://github.com/SalinatedCoffee) [ko support](https://polyglot.untra.io/ko/2023/02/27/korean-support/) * [@aturret](https://github.com/aturret) [zh-CN support](https://polyglot.untra.io/zh-CN/2023/06/08/polyglot-1.6.0-chinese-support/) * [@dougieh](https://github.com/dougieh) [1.5.1](https://polyglot.untra.io/2022/10/01/polyglot-1.5.1/) * [@pandermusubi](https://github.com/PanderMusubi) [nl support](https://polyglot.untra.io/nl/2022/01/15/dutch-site-support/) * [@obfusk](https://github.com/obfusk) [1.5.0](https://polyglot.untra.io/2021/07/17/polyglot-1.5.0/) * [@eighthave](https://github.com/eighthave) [1.5.0](https://polyglot.untra.io/2021/07/17/polyglot-1.5.0/) * [@george-gca](https://github.com/george-gca) [pt-BR support](https://polyglot.untra.io/pt-BR/2024/02/29/localized-variables.md) ### Other Websites Built with Polyglot Feel free to open a PR and list your multilingual blog here you may want to share: * [**Polyglot project website**](https://polyglot.untra.io) * [LogRhythm Corporate Website](https://logrhythm.com) * [All Over Earth](https://allover.earth/) * [Hanare Cafe in Toshijima, Japan](https://hanarecafe.com) * [F-Droid](https://f-droid.org) * [Ubuntu MATE](https://ubuntu-mate.org) * [Leo3418 blog](https://leo3418.github.io/) * [Gaphor](https://gaphor.org) * [Yi Yunseok's personal blog website](https://Yi-Yunseok.GitHub.io) * [Tarlogic Cybersecurity](https://www.tarlogic.com/) * [A beautiful, simple, clean, and responsive Jekyll theme for academics](https://github.com/george-gca/multi-language-al-folio) * [AnotherTurret just another study note blog](https://aturret.space/) * [Diciotech is a collaborative online tech dictionary](https://diciotech.netlify.app/) * [Yunseo Kim's Study Notes](https://www.yunseo.kim/) ## 2.0 Roadmap * [x] - **site language**: portuguese Brazil `pt-BR` * [ ] - **site language**: portuguese Portugal `pt-PT` * [ ] - **site language**: arabic `ar` * [ ] - **site language**: japanese `ja` * [x] - **site language**: russian `ru` * [x] - **site language**: dutch `nl` * [x] - **site language**: korean `ko` * [x] - **site language**: hebrew `he` * [x] - **site language**: chinese China `zh-CN` * [ ] - **site language**: chinese Taiwan `zh-TW` * [ ] - get whitelisted as an official github-pages jekyll plugin * [x] - update CI provider ## Copyright Copyright (c) Samuel Volin 2025. License: MIT polyglot-1.9.0/Rakefile 0000664 0000000 0000000 00000000131 14743006212 0015031 0 ustar 00root root 0000000 0000000 require "rspec/core/rake_task" RSpec::Core::RakeTask.new(:spec) task :default => [:spec] polyglot-1.9.0/jekyll-polyglot.gemspec 0000664 0000000 0000000 00000001121 14743006212 0020072 0 ustar 00root root 0000000 0000000 Gem::Specification.new do |s| s.name = 'jekyll-polyglot' s.version = '1.9.0' s.date = '2025-01-18' s.summary = 'I18n plugin for Jekyll Blogs' s.description = 'Fast open source i18n plugin for Jekyll blogs.' s.authors = ['Samuel Volin'] s.email = 'untra.sam@gmail.com' s.files = ['README.md', 'LICENSE'] + Dir['lib/**/*'] s.homepage = 'https://polyglot.untra.io/' s.license = 'MIT' s.add_runtime_dependency('jekyll', '>= 3.0', '>= 4.0') s.required_ruby_version = '>= 2.7.0' s.required_rubygems_version = '>= 2.7.0' end polyglot-1.9.0/lib/ 0000775 0000000 0000000 00000000000 14743006212 0014137 5 ustar 00root root 0000000 0000000 polyglot-1.9.0/lib/jekyll-polyglot.rb 0000664 0000000 0000000 00000000032 14743006212 0017620 0 ustar 00root root 0000000 0000000 require "jekyll/polyglot" polyglot-1.9.0/lib/jekyll/ 0000775 0000000 0000000 00000000000 14743006212 0015431 5 ustar 00root root 0000000 0000000 polyglot-1.9.0/lib/jekyll/polyglot.rb 0000664 0000000 0000000 00000000237 14743006212 0017631 0 ustar 00root root 0000000 0000000 require 'jekyll' require_relative 'polyglot/liquid' require_relative 'polyglot/patches' require_relative 'polyglot/hooks' require_relative 'polyglot/version' polyglot-1.9.0/lib/jekyll/polyglot/ 0000775 0000000 0000000 00000000000 14743006212 0017302 5 ustar 00root root 0000000 0000000 polyglot-1.9.0/lib/jekyll/polyglot/hooks.rb 0000664 0000000 0000000 00000000105 14743006212 0020746 0 ustar 00root root 0000000 0000000 require_relative 'hooks/coordinate' require_relative 'hooks/process' polyglot-1.9.0/lib/jekyll/polyglot/hooks/ 0000775 0000000 0000000 00000000000 14743006212 0020425 5 ustar 00root root 0000000 0000000 polyglot-1.9.0/lib/jekyll/polyglot/hooks/assets-toggle.rb 0000664 0000000 0000000 00000000332 14743006212 0023531 0 ustar 00root root 0000000 0000000 # Jekyll::Hooks.register :site, :after_init do |site| # if site.config['assets'] # if site.active_lang != site.default_lang # then jekyll.sprockets.asset_config['autowrite'] = false # end # end # end polyglot-1.9.0/lib/jekyll/polyglot/hooks/coordinate.rb 0000664 0000000 0000000 00000001656 14743006212 0023111 0 ustar 00root root 0000000 0000000 # hook to coordinate blog posts and pages into distinct urls, # and remove duplicate multilanguage posts and pages Jekyll::Hooks.register :site, :post_read do |site| hook_coordinate(site) end def hook_coordinate(site) # Copy the language specific data, by recursively merging it with the default data. # Favour active_lang first, then default_lang, then any non-language-specific data. # See: https://www.ruby-forum.com/topic/142809 merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 } if site.data.include?(site.default_lang) site.data = site.data.merge(site.data[site.default_lang], &merger) end if site.data.include?(site.active_lang) site.data = site.data.merge(site.data[site.active_lang], &merger) end site.collections.each do |_, collection| collection.docs = site.coordinate_documents(collection.docs) end site.pages = site.coordinate_documents(site.pages) end polyglot-1.9.0/lib/jekyll/polyglot/hooks/process.rb 0000664 0000000 0000000 00000000441 14743006212 0022427 0 ustar 00root root 0000000 0000000 # hook to make a call to process rendered documents, Jekyll::Hooks.register :site, :post_render do |site| hook_process(site) end def hook_process(site) site.collections.each do |_, collection| site.process_documents(collection.docs) end site.process_documents(site.pages) end polyglot-1.9.0/lib/jekyll/polyglot/liquid.rb 0000664 0000000 0000000 00000000247 14743006212 0021121 0 ustar 00root root 0000000 0000000 module Jekyll module Polyglot module Liquid require_relative 'liquid/tags/i18n_headers' require_relative 'liquid/tags/static_href' end end end polyglot-1.9.0/lib/jekyll/polyglot/liquid/ 0000775 0000000 0000000 00000000000 14743006212 0020571 5 ustar 00root root 0000000 0000000 polyglot-1.9.0/lib/jekyll/polyglot/liquid/tags/ 0000775 0000000 0000000 00000000000 14743006212 0021527 5 ustar 00root root 0000000 0000000 polyglot-1.9.0/lib/jekyll/polyglot/liquid/tags/i18n_headers.rb 0000664 0000000 0000000 00000002366 14743006212 0024335 0 ustar 00root root 0000000 0000000 module Jekyll module Polyglot module Liquid class I18nHeadersTag < ::Liquid::Tag def initialize(tag_name, text, tokens) super @url = text @url.strip! @url.chomp! '/' end def render(context) site = context.registers[:site] permalink = context.registers[:page]['permalink'] permalink_lang = context.registers[:page]['permalink_lang'] site_url = @url.empty? ? site.config['url'] : @url i18n = "\n" i18n += "\n" site.languages.each do |lang| next if lang == site.default_lang url = permalink_lang && permalink_lang[lang] ? permalink_lang[lang] : permalink i18n += "\n" end i18n end end end end end Liquid::Template.register_tag('I18n_Headers', Jekyll::Polyglot::Liquid::I18nHeadersTag) Liquid::Template.register_tag('i18n_headers', Jekyll::Polyglot::Liquid::I18nHeadersTag) polyglot-1.9.0/lib/jekyll/polyglot/liquid/tags/static_href.rb 0000664 0000000 0000000 00000002021 14743006212 0024342 0 ustar 00root root 0000000 0000000 module Jekyll module Polyglot module Liquid class StaticHrefTag < :: Liquid::Block def initialize(tag_name, params, tokens) super end def render(context) text = super href_attrs = text.strip.split '=' valid = (href_attrs.length == 2 && href_attrs[0] == 'href') && href_attrs[1].start_with?('"') && href_attrs[1].end_with?('"') unless valid raise Liquid::SyntaxError, "static_href parameters must include match href=\"...\" attribute param, eg. href=\"http://example.com\, href=\"/about\", href=\"/\" , instead got:\n#{text}" end href_value = href_attrs[1] # href writes out as ferh="..." explicitly wrong, to be cauaght by seperate processor for nonrelativized links "ferh=#{href_value}" end end end end end Liquid::Template.register_tag('Static_Href', Jekyll::Polyglot::Liquid::StaticHrefTag) Liquid::Template.register_tag('static_href', Jekyll::Polyglot::Liquid::StaticHrefTag) polyglot-1.9.0/lib/jekyll/polyglot/patches.rb 0000664 0000000 0000000 00000000125 14743006212 0021254 0 ustar 00root root 0000000 0000000 require_relative 'patches/jekyll/site' require_relative 'patches/jekyll/static_file' polyglot-1.9.0/lib/jekyll/polyglot/patches/ 0000775 0000000 0000000 00000000000 14743006212 0020731 5 ustar 00root root 0000000 0000000 polyglot-1.9.0/lib/jekyll/polyglot/patches/jekyll/ 0000775 0000000 0000000 00000000000 14743006212 0022223 5 ustar 00root root 0000000 0000000 polyglot-1.9.0/lib/jekyll/polyglot/patches/jekyll/site.rb 0000664 0000000 0000000 00000023227 14743006212 0023522 0 ustar 00root root 0000000 0000000 require 'etc' include Process module Jekyll class Site attr_reader :default_lang, :languages, :exclude_from_localization, :lang_vars, :lang_from_path attr_accessor :file_langs, :active_lang def prepare @file_langs = {} fetch_languages @parallel_localization = config.fetch('parallel_localization', true) @lang_from_path = config.fetch('lang_from_path', false) @exclude_from_localization = config.fetch('exclude_from_localization', []).map do |e| if File.directory?(e) && e[-1] != '/' "#{e}/" else e end end end def fetch_languages @default_lang = config.fetch('default_lang', 'en') @languages = config.fetch('languages', ['en']).uniq @keep_files += (@languages - [@default_lang]) @active_lang = @default_lang @lang_vars = config.fetch('lang_vars', []) end alias process_orig process def process prepare all_langs = (@languages + [@default_lang]).uniq if @parallel_localization nproc = Etc.nprocessors pids = {} begin all_langs.each do |lang| pids[lang] = fork do process_language lang end while pids.length >= (lang == all_langs[-1] ? 1 : nproc) sleep 0.1 pids.map do |lang, pid| next unless waitpid pid, Process::WNOHANG pids.delete lang raise "Polyglot subprocess #{pid} (#{lang}) failed (#{$?.exitstatus})" unless $?.success? end end end rescue Interrupt all_langs.each do |lang| next unless pids.key? lang puts "Killing #{pids[lang]} : #{lang}" kill('INT', pids[lang]) end end else all_langs.each do |lang| process_language lang end end Jekyll::Hooks.trigger :polyglot, :post_write end alias site_payload_orig site_payload def site_payload payload = site_payload_orig payload['site']['default_lang'] = default_lang payload['site']['languages'] = languages payload['site']['active_lang'] = active_lang lang_vars.each do |v| payload['site'][v] = active_lang end payload end def process_language(lang) @active_lang = lang config['active_lang'] = @active_lang lang_vars.each do |v| config[v] = @active_lang end if @active_lang == @default_lang then process_default_language else process_active_language end end def process_default_language old_include = @include process_orig @include = old_include end def process_active_language old_dest = @dest old_exclude = @exclude @file_langs = {} @dest = "#{@dest}/#{@active_lang}" @exclude += @exclude_from_localization process_orig @dest = old_dest @exclude = old_exclude end def split_on_multiple_delimiters(string) delimiters = ['.', '/'] regex = Regexp.union(delimiters) string.split(regex) end def derive_lang_from_path(doc) unless @lang_from_path return nil end segments = split_on_multiple_delimiters(doc.path) # loop through all segments and check if they match the language regex segments.each do |segment| if @languages.include?(segment) return segment end end # loop through all segments and check if they match the language regex segments.each do |segment| if @languages.include?(segment) return segment end end nil end # assigns natural permalinks to documents and prioritizes documents with # active_lang languages over others. If lang is not set in front matter, # then this tries to derive from the path, if the lang_from_path is set. # otherwise it will assign the document to the default_lang def coordinate_documents(docs) regex = document_url_regex approved = {} docs.each do |doc| lang = doc.data['lang'] || derive_lang_from_path(doc) || @default_lang lang_exclusive = doc.data['lang-exclusive'] || [] url = doc.url.gsub(regex, '/') page_id = doc.data['page_id'] || url doc.data['permalink'] = url if doc.data['permalink'].to_s.empty? && !doc.data['lang'].to_s.empty? # skip entirely if nothing to check next if @file_langs.nil? # skip this document if it has already been processed next if @file_langs[page_id] == @active_lang # skip this document if it has a fallback and it isn't assigned to the active language next if @file_langs[page_id] == @default_lang && lang != @active_lang # skip this document if it has lang-exclusive defined and the active_lang is not included next if !lang_exclusive.empty? && !lang_exclusive.include?(@active_lang) approved[page_id] = doc @file_langs[page_id] = lang end approved.values.each { |doc| assignPageRedirects(doc, docs) } approved.values.each { |doc| assignPageLanguagePermalinks(doc, docs) } approved.values end def assignPageRedirects(doc, docs) pageId = doc.data['page_id'] if !pageId.nil? && !pageId.empty? lang = doc.data['lang'] || derive_lang_from_path(doc) || @default_lang langPrefix = lang === @default_lang ? '' : "#{lang}/" redirectDocs = docs.select do |dd| doclang = dd.data['lang'] || derive_lang_from_path(dd) || @default_lang dd.data['page_id'] == pageId && doclang != lang && dd.data['permalink'] != doc.data['permalink'] end redirects = redirectDocs.map { |dd| dd.data['permalink'] } doc.data['redirect_from'] = redirects end end def assignPageLanguagePermalinks(doc, docs) pageId = doc.data['page_id'] if !pageId.nil? && !pageId.empty? unless doc.data['permalink_lang'] then doc.data['permalink_lang'] = {} end permalinkDocs = docs.select do |dd| dd.data['page_id'] == pageId end permalinkDocs.each do |dd| doclang = dd.data['lang'] || derive_lang_from_path(dd) || @default_lang doc.data['permalink_lang'][doclang] = dd.data['permalink'] end end end # performs any necessary operations on the documents before rendering them def process_documents(docs) # return if @active_lang == @default_lang url = config.fetch('url', false) rel_regex = relative_url_regex(false) abs_regex = absolute_url_regex(url, false) non_rel_regex = relative_url_regex(true) non_abs_regex = absolute_url_regex(url, true) docs.each do |doc| unless @active_lang == @default_lang then relativize_urls(doc, rel_regex) end correct_nonrelativized_urls(doc, non_rel_regex) if url unless @active_lang == @default_lang then relativize_absolute_urls(doc, abs_regex, url) end correct_nonrelativized_absolute_urls(doc, non_abs_regex, url) end end end # a regex that matches urls or permalinks with i18n prefixes or suffixes # matches /en/foo , .en/foo , foo.en/ and other simmilar default urls # made by jekyll when parsing documents without explicitly set permalinks def document_url_regex regex = '' (@languages || []).each do |lang| regex += "([\/\.]#{lang}[\/\.])|" end regex.chomp! '|' /#{regex}/ end # a regex that matches relative urls in a html document # matches href="baseurl/foo/bar-baz" href="/foo/bar-baz" and others like it # avoids matching excluded files. prepare makes sure # that all @exclude dirs have a trailing slash. def relative_url_regex(disabled = false) regex = '' unless disabled @exclude.each do |x| regex += "(?!#{x})" end @languages.each do |x| regex += "(?!#{x}\/)" end end start = disabled ? 'ferh' : 'href' %r{#{start}="?#{@baseurl}/((?:#{regex}[^,'"\s/?.]+\.?)*(?:/[^\]\[)("'\s]*)?)"} end # a regex that matches absolute urls in a html document # matches href="http://baseurl/foo/bar-baz" and others like it # avoids matching excluded files. prepare makes sure # that all @exclude dirs have a trailing slash. def absolute_url_regex(url, disabled = false) regex = '' unless disabled @exclude.each do |x| regex += "(?!#{x})" end @languages.each do |x| regex += "(?!#{x}\/)" end end start = disabled ? 'ferh' : 'href' %r{(?