diff --git a/.htaccess b/.htaccess
index b24dbb7c..fa2094fe 100644
--- a/.htaccess
+++ b/.htaccess
@@ -24,14 +24,50 @@ RewriteBase /
AddType application/json apple-app-site-association
# Deny crowdin.yml
-RewriteRule ^crowdin.yml$ = [F,L]
+RewriteRule "^crowdin.yml$" = [F,L]
# Custom error messages (need to pass the original request)
-ErrorDocument 404 /_includes/errors/404
+ErrorDocument 404 /_includes/errors/404.php
+
+RewriteRule "^_includes/errors/404(.php)?$" "/_includes/errors/404.php" [END]
# apple-app-site-association
RewriteRule "^.well-known/apple-app-site-association$" "/.well-known/apple-app-site-association.json" [L]
+# ##################################################################
+# Redirections - before rewriting
+# ##################################################################
+
+# ------------------------------------------------------------------
+# PHP and Markdown redirections
+# ------------------------------------------------------------------
+
+# Remove index.md or index.php and redirect (and stop processing)
+RewriteRule "^((.+)/)?index(\.md|\.php)?$" "$1" [R,L]
+
+# Remove .php extension and redirect
+RewriteRule "^(.+)\.php$" "$1" [R,L]
+RewriteRule "^(.+)\.md$" "$1" [R,L]
+
+# Redirect folder without / to include /
+RewriteCond "%{DOCUMENT_ROOT}/$1" -d
+RewriteCond "%{DOCUMENT_ROOT}/$1.php" !-f
+RewriteCond "%{DOCUMENT_ROOT}/$1.md" !-f
+RewriteRule "^(.+[^/])$" "$1/" [R,END]
+
+# ------------------------------------------------------------------
+# Known path redirections
+# ------------------------------------------------------------------
+
+# Redirect /archive/downloads.php"
+RewriteRule "^archive/downloads(.php)?$" "/downloads/archive/" [NC,R=301,END,QSA]
+
+# ios and iphone and ipad to iphone-and-ipad
+RewriteRule "^(ios|iphone|ipad)(/.*)?$" "/iphone-and-ipad$2" [NC,R=301,END,QSA]
+
+# Redirect Android/iOS app to help homepage
+RewriteRule "^(android|iphone-and-ipad)/app(.*)$" "https://help.keyman.com/products/$1/" [NC,R=301,END]
+
# macosx and macos to mac (ignore case)
RewriteRule "^(macosx|macos)\b(.*)$" "/mac$2" [NC,R=301,END,QSA]
@@ -39,29 +75,22 @@ RewriteRule "^(macosx|macos)\b(.*)$" "/mac$2" [NC,R=301,END,QSA]
RewriteRule "^plus.*" "/" [NC,R=301,END,QSA]
# Redirect PHP unit tests
-RewriteRule "^tests(\/.*)?" "/" [NC,R=301,END,QSA]
+RewriteRule "^tests(/.*)?" "/" [NC,R=301,END,QSA]
# /donate -> donate.keyman.com
-RedirectMatch 301 "^(?i)/donate(\/.*)?" "https://donate.keyman.com"
+RedirectMatch 301 "^(?i)/donate(/.*)?" "https://donate.keyman.com"
# /privacy -> SIL Privacy policy
-RedirectMatch 301 "^(?i)/privacy(\/.*)?" "https://software.sil.org/language-software-privacy-policy/"
+RedirectMatch 301 "^(?i)/privacy(/.*)?" "https://software.sil.org/language-software-privacy-policy/"
# desktop to windows
RewriteRule "^desktop(/.*)?" "/windows$1" [NC,R=301,END,QSA]
-# releases-tier/download
-# note: the tier is currently ignored
-RewriteRule "^downloads/releases/(alpha|beta|stable)/(.+)$" "/downloads/releases/_version_downloads.php?tier=$1&version=$2" [END]
-
-# releases-download
-RewriteRule "^downloads/releases/(.+)$" "/downloads/releases/_version_downloads.php?version=$1" [END]
-
-# index
-RewriteRule "^downloads/releases(\/)?$" "/downloads" [R,END]
+# releases-download index
+RewriteRule "^downloads/releases(/)?$" "/downloads" [R,END]
# CLDR -> LDML
-RewriteRule "^cldr(\/)?$" "/ldml" [R=301,END]
+RewriteRule "^cldr(/)?$" "/ldml" [R=301,END]
#
# Keyboard landing pages (TODO)
@@ -86,59 +115,14 @@ RewriteRule "^keyboards/(.*)/share(/?)$" "/keyboards/share/$1" [R=301]
# /keyboard/{content} to /keyboards/...
RewriteRule "^keyboard(/.*)$" "/keyboards$1" [R,END]
-#
-# Install | Download | Share | bare | .json -->
-#
-
-# /keyboards/install/[id] to /keyboards/install.php
-RewriteRule "^keyboards/install/([^/]+)$" "/keyboards/install.php?id=$1" [END,QSA]
-
-# /keyboards/download/[id] to /keyboards/keyboard.php
-# This formerly redirected to a download, but we no longer need it; keep it for
-# legacy links
-RewriteRule "^keyboards/download/([^/]+)$" "/keyboards/keyboard.php?id=$1" [END,QSA]
-
-# /keyboards/share/[id] to /keyboards/share.php
-# if the keyboard exists in the repo, then share.php will redirect to /keyboards/
-RewriteRule "^keyboards/share/([^/]+)$" "/keyboards/share.php?id=$1" [END,QSA]
-
-# /keyboards/{id}.json to /keyboards/keyboard.json.php
-RewriteRule "^keyboards/(?!keyboard.json)(.*)\.json$" "/keyboards/keyboard.json.php?id=$1" [END]
-
-# /keyboards/{id} to /keyboards/keyboard.php
-RewriteRule "^keyboards/(?!index\.php|install|keyboard|session|share)([^/]+)$" "/keyboards/keyboard.php?id=$1" [END,QSA]
-
-
-#
-# Search
-#
-
-# /keyboards?q=... to /keyboards/index.php
-# RewriteRule "^keyboards$" "/keyboards/index.php" [L]
-
-# /keyboards/languages to /keyboards/index.php
-RewriteRule "^keyboards/languages/(.*)" "/keyboards/index.php?q=l:id:$1" [END,QSA]
-
-# /keyboards/download to /keyboards/download.php
-RewriteRule "^keyboards/download(.php)?" "/keyboards/download.php" [END,QSA]
-
-# /keyboards/legacy to /keyboards/keyboard.php
-RewriteRule "^keyboards/legacy/(.*)" "/keyboards/keyboard.php?legacy=$1" [END]
-
-# /keyboards/countries to /keyboards/index.php
-RewriteRule "^keyboards/countries/(.*)" "/keyboards/index.php?q=c:id:$1" [END]
-
# Synonym paths
# 10.0 to 15.0
# /1X.0 to /1X landing page
-RedirectMatch "^/1([0-5])(\.0)\/?" "/1$1/"
-
-# ios
-RedirectMatch "^/(?!iphone-and-ipad)(ios|iphone|ipad)(\/.*)?" "/iphone-and-ipad$2"
+RedirectMatch "^/1([0-5])(\.0)(/?)" "/1$1/"
# Connect With Art landing page
-RedirectMatch "/connectwithart(\/|$)" "https://sites.google.com/sil.org/connectwithart/home"
+RedirectMatch "/connectwithart(/|$)" "https://sites.google.com/sil.org/connectwithart/home"
RedirectMatch "^/lt4all(/?)$" "/ldml/lt4all"
@@ -180,52 +164,149 @@ RedirectMatch "^/(french|german|italian|spanish|swedish)(/?)$" "/keyboards
# dedicated-keyboard-landing pages
RedirectMatch 301 "^/(amharic|burmese|cameroon|ethiopic|eurolatin|greek|ipa|sinhala|tamil|tibetan|tigrigna|urdu)(/.*)?$" "/keyboards/h/$1$2"
+# ------------------------------------------------------------------
+# i18n redirect --> /file to /file
+# ------------------------------------------------------------------
+
#
-# PHP and Markdown rewriting
+# if $1 is a folder or file in /_content, then redirect to currentlang (en?)
+# e.g. would redirect windows/download --> en/windows/download/
+RewriteCond "%{DOCUMENT_ROOT}/_content/$1.php" -f [OR]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$1.md" -f [OR]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$1" -d
+RewriteRule "^(.*)$" "en/$1" [R,L]
+
#
+# Paths involving queries (don't match on file/directory)
+RewriteRule "^(downloads/releases|keyboards)/(.+)$" "en/$1/$2" [R,L]
-# Remove index or index.php and redirect (and stop processing)
-RewriteCond "$1" -d
-RewriteRule "^((.+)/)?index(\.php)?$" "$1" [R,L]
+# ##################################################################
+# Rewriting
+# ##################################################################
-# Remove .php extension and redirect
-RewriteCond "$1.php" -f
-RewriteCond "$1" !-d
-RewriteRule "^(.+)\.php$" "$1" [R,L]
+# ------------------------------------------------------------------
+# top-level content without i18n - _control/, go/, _test/, cdn
+# ------------------------------------------------------------------
-# Redirect folder without / to include /
-RewriteCond "{DOCUMENT_ROOT}/$1" -d
-RewriteCond "{DOCUMENT_ROOT}/$1.php" !-f
-RewriteCond "{DOCUMENT_ROOT}/$1.md" !-f
-RewriteRule "^(.+[^/])$" "$1/" [R,END]
+# No i18n - won't go to _content
+RewriteCond "%{DOCUMENT_ROOT}/$1/$2.php" -f
+RewriteRule "^(_control|go|_test)/(.+)$" "/$1/$2.php" [END]
+
+RewriteCond "%{DOCUMENT_ROOT}/$1/$2.md" -f
+RewriteRule "^(_control|go|_test)/(.+)$" "/_includes/includes/md/mdhost.php?file=$1/$2.md" [END]
+
+RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" -f
+RewriteRule "^(_control|go|_test)(/?)$" "/_includes/includes/md/mdhost.php?file=$1/index.md" [END]
+
+RewriteCond "%{DOCUMENT_ROOT}/cdn/$1$2" -f
+RewriteRule "^cdn/(.+\.)(gif|js|png|svg)$" "/cdn/$1$2" [END]
+
+
+#
+# keyboards Install | Download | Share | bare | .json -->
+#
+
+# /keyboards/install/[id] to /keyboards/install.php
+RewriteRule "^(en)/keyboards/install/([^/]+)$" "/_content/keyboards/install.php?id=$2&lang=$1" [END,QSA]
+
+# /keyboards/download/[id] to /keyboards/keyboard.php
+# This formerly redirected to a download, but we no longer need it; keep it for
+# legacy links
+RewriteRule "^(en)/keyboards/download/([^/]+)$" "/_content/keyboards/keyboard.php?id=$2&lang=$1" [END,QSA]
+
+# /keyboards/share/[id] to /keyboards/share.php
+# if the keyboard exists in the repo, then share.php will redirect to /keyboards/
+RewriteRule "^(en)/keyboards/share/([^/]+)$" "/_content/keyboards/share.php?id=$2&lang=$1" [END,QSA]
+
+# /keyboards/{id}.json to /keyboards/keyboard.json.php
+RewriteRule "^(en)/keyboards/(?!keyboard.json)(.*)\.json$" "/_content/keyboards/keyboard.json.php?id=$2&lang=$1" [END]
+
+# /keyboards/{id} to /keyboards/keyboard.php
+RewriteRule "^(en)/keyboards/(?!index\.php|install|keyboard|session|share)([^/]+)$" "/_content/keyboards/keyboard.php?id=$2&lang=$1" [END,QSA]
+
+#
+# keyboards search
+#
+
+# /keyboards/languages to /keyboards/index.php
+RewriteRule "^(en)/keyboards/languages/(.*)" "/_content/keyboards/index.php?q=l:id:$2&lang=$1" [END,QSA]
+
+# /keyboards/download to /keyboards/download.php
+RewriteRule "^(en)/keyboards/download(.php)?" "/_content/keyboards/download.php?lang=$1" [END,QSA]
+
+# /keyboards/legacy to /keyboards/keyboard.php
+RewriteRule "^(en)/keyboards/legacy/(.*)" "/_content/keyboards/keyboard.php?legacy=$2&lang=$1" [END]
+
+# /keyboards/countries to /keyboards/index.php
+RewriteRule "^(en)/keyboards/countries/(.*)" "/_content/keyboards/index.php?q=c:id:$2&lang=$1" [END]
+
+
+#
+# contact/exception
+#
+
+# /contact/exception to /contact/exception.php
+RewriteRule "^(en)/contact/exception(.php)?" "/_content/contact/exception.php?lang=$1" [END,QSA]
+
+RewriteRule "^(en)/contact/exception?id=(.+)$" "/_content/contact/exception?id=$2&lang=$1" [END]
+
+#
+# ios
+#
+RewriteRule "^(en)/(iphone|ipad)(/.*)?" "/_content/iphone-and-ipad/$3?lang=$1" [END,QSA]
+
+#
+# downloads/releases
+#
+
+# releases-tier/download
+# note: the tier is currently ignored
+RewriteRule "^(en)/downloads/releases/(alpha|beta|stable)/(.+)$" "/_content/downloads/releases/_version_downloads.php?tier=$2&version=$3&lang=$1" [END]
+
+# releases-download
+RewriteRule "^(en)/downloads/releases/(.+)$" "/_content/downloads/releases/_version_downloads.php?version=$2&lang=$1" [END]
+
+#
+# Assets don't use lang param
#
-# PHP rewriting
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2" -f
+RewriteRule "^(en)/(.+)$" "/_content/$2" [END]
+
+# TODO: do we want en/lao --> en/keyboards/basic_kbdlao? as well as /lao --> ...
+
+#
+# PHP and Markdown rewriting
#
# TODO: mdhost currently in a different path than help.keyman
+# TODO: en --> should be a bcp-47 type 'lang' match (e.g. ab[-x][-y]) ignore case, keep it a fairly loose expression [a-z][a-z][a-z]?(-...)?
+
+##############################################
+
# Rewrite file to file.md
-RewriteCond "%{DOCUMENT_ROOT}/$1.md" -f
-RewriteRule "^(.+)$" "/_includes/includes/md/mdhost.php?file=$1.md" [END]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2.md" -f
+RewriteRule "^(en)/(.+)$" "/_includes/includes/md/mdhost.php?file=_content/$2.md&lang=$1" [END]
# Rewrite file to file.php
-RewriteCond "%{DOCUMENT_ROOT}/$1.php" -f
-RewriteCond "%{DOCUMENT_ROOT}/$1.md" !-f
-RewriteRule "^(.+)$" "$1.php" [END]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2.php" -f
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2.md" !-f
+RewriteRule "^(en)/(.+)$" "/_content/$2.php?lang=$1" [END]
# Rewrite folder/ to folder/index.md
-RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" -f
-RewriteRule "^(.+)/$" "/_includes/includes/md/mdhost.php?file=$1/index.md" [END]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2/index.md" -f
+RewriteRule "^(en)/(.+)/$" "/_includes/includes/md/mdhost.php?file=_content/$2/index.md&lang=$1" [END]
# Rewrite folder/ to folder/index.php
-RewriteCond "%{DOCUMENT_ROOT}/$1/index.php" -f
-RewriteCond "%{DOCUMENT_ROOT}/$1/index.md" !-f
-RewriteRule "^(.+)/$" "$1/index.php" [END]
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2/index.php" -f
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2/index.md" !-f
+RewriteRule "^(en)/(.+)/$" "/_content/$2/index.php?lang=$1" [END]
+
+# Root page
+RewriteRule "^(en)/$" "/_content/index.php?lang=$1" [END]
# Finally, append the terminating slash for folders, given it is no longer
# done automatically because we put DirectorySlash off
-RewriteCond %{REQUEST_FILENAME} -d
-RewriteRule "^(.*)([^/])$" "$1$2/" [R]
-
-
+RewriteCond "%{DOCUMENT_ROOT}/_content/$2$3" -d
+RewriteRule "^(en)(.*)([^/])?$" "$1$2$3/" [R,QSA]
diff --git a/_content/android/app/.htaccess b/_content/android/app/.htaccess
deleted file mode 100644
index 544cf4cf..00000000
--- a/_content/android/app/.htaccess
+++ /dev/null
@@ -1,3 +0,0 @@
-
-# Redirect /android/app to help.keyman.com
-RedirectMatch ".*" "https://help.keyman.com/products/android/"
diff --git a/_content/archive/.htaccess b/_content/archive/.htaccess
deleted file mode 100644
index 0599591b..00000000
--- a/_content/archive/.htaccess
+++ /dev/null
@@ -1,3 +0,0 @@
-
-# Redirect /archive/downloads.php"
-RedirectMatch 301 "/archive/downloads.php" "/downloads/archive/"
diff --git a/_content/developer/index.php b/_content/developer/index.php
index c44079ed..f2cf45be 100644
--- a/_content/developer/index.php
+++ b/_content/developer/index.php
@@ -17,14 +17,14 @@
?>
Keyman Developer
-Keyman Developer is the most powerful tool for creating
+
Keyman Developer is the most powerful tool for creating
keyboard layouts for any popular platform for any language around the world. Build keyboards layouts for desktop,
web, tablet and phone. Optimise your keyboards for each platform, including touch-and-hold keys and alternative layers.
diff --git a/_content/developer/keymanweb/index.php b/_content/developer/keymanweb/index.php
index eb817d20..d165cb72 100644
--- a/_content/developer/keymanweb/index.php
+++ b/_content/developer/keymanweb/index.php
@@ -19,7 +19,7 @@
KeymanWeb Source Code and Development
KeymanWeb = $stable_version; ?> is an Open Source input method system for the web, supporting both desktops and touch devices. Keyboard layouts for
- use with KeymanWeb can be created with the free download Keyman Developer (Windows).
+ use with KeymanWeb can be created with the free download Keyman Developer (Windows).
Add KeymanWeb to a Website
@@ -45,11 +45,11 @@
@@ -97,9 +97,9 @@
diff --git a/_content/iphone-and-ipad/app/.htaccess b/_content/iphone-and-ipad/app/.htaccess
deleted file mode 100644
index c798b232..00000000
--- a/_content/iphone-and-ipad/app/.htaccess
+++ /dev/null
@@ -1,3 +0,0 @@
-
-# Redirect /iphone-and-ipad/app to help.keyman.com
-RedirectMatch "/iphone-and-ipad/app/.*" "https://help.keyman.com/products/iphone-and-ipad/"
diff --git a/_content/keyboards/h/amharic/index.php b/_content/keyboards/h/amharic/index.php
index ff11015d..5055404b 100644
--- a/_content/keyboards/h/amharic/index.php
+++ b/_content/keyboards/h/amharic/index.php
@@ -138,7 +138,7 @@
Gurage Legacy
Harari
Tigre
- Tigrigna (Eritrea)
+ Tigrigna (Eritrea)
Tigrigna (Ethiopia)
diff --git a/_content/keyboards/h/sinhala/garp/index.php b/_content/keyboards/h/sinhala/garp/index.php
index 7c442de0..351d810d 100644
--- a/_content/keyboards/h/sinhala/garp/index.php
+++ b/_content/keyboards/h/sinhala/garp/index.php
@@ -35,19 +35,19 @@
Download Now
- Learn more about Keyman for Windows
+ Learn more about Keyman for Windows
@@ -92,25 +92,25 @@
Download a Sinhala keyboard on these devices:
@@ -91,25 +91,25 @@
Download a Sinhala keyboard on these devices:
-
+
Bookmarklet
diff --git a/_content/keyboards/h/tamil/index.php b/_content/keyboards/h/tamil/index.php
index 62716a27..f7e37cce 100644
--- a/_content/keyboards/h/tamil/index.php
+++ b/_content/keyboards/h/tamil/index.php
@@ -102,7 +102,7 @@
Download a Tamil keyboard on these devices:
-
+
iPhone
diff --git a/_content/keyboards/h/tigrigna/index.php b/_content/keyboards/h/tigrigna/index.php
index a11b8b32..4f6838d5 100644
--- a/_content/keyboards/h/tigrigna/index.php
+++ b/_content/keyboards/h/tigrigna/index.php
@@ -16,7 +16,7 @@
Type in Tigrigna on iPhone, iPad, Windows, macOS, Linux, and Android. Our Tigrigna keyboards works with Microsoft Word, Photoshop, Facebook, Twitter, email and thousands of other applications.
- Click here for Tigirigna (Eritrea)
+ Click here for Tigirigna (Eritrea)
@@ -115,7 +115,7 @@
Type in other Ethiopic languages such as: