Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6f8fdae
fix: .htaccess for including <lang> in the URL
darcywong00 Mar 24, 2026
863f677
fix: more rewrites involving _content
darcywong00 Mar 25, 2026
d98b236
fix: Add lang to Head.php
darcywong00 Mar 30, 2026
f4d6d99
fix: redirects to currentlang
darcywong00 Mar 31, 2026
91d69b5
fix: remove .php from links
darcywong00 Mar 31, 2026
cd9fd45
tweak regex
darcywong00 Apr 1, 2026
8b3f67e
Merge branch 'epic/i18n-url-scheme' into fix/lang/htaccess
darcywong00 Apr 1, 2026
a0f3d86
fix 404
darcywong00 Apr 2, 2026
3804817
fix en routing
darcywong00 Apr 2, 2026
839fb40
fix: Handle _control, go, and _test
darcywong00 Apr 2, 2026
1583b34
refactor: reorder .htaccess
darcywong00 Apr 2, 2026
7ca0e01
chore: remove old root rule
darcywong00 Apr 2, 2026
57ad35d
fix: downloads/releases paths
darcywong00 Apr 2, 2026
37273da
fix: keyboard rewrites
darcywong00 Apr 2, 2026
95bbf29
chore: more cleanup
darcywong00 Apr 2, 2026
bf9897e
fix /archive/downloads redirect
darcywong00 Apr 6, 2026
7634f84
fix: keyboards/download query
darcywong00 Apr 6, 2026
93bad37
fix /contact/exception
darcywong00 Apr 6, 2026
53ba79a
fix menu link to "Help and Documentation"
darcywong00 Apr 6, 2026
35f00a4
chore: cleanup more _test paths
darcywong00 Apr 6, 2026
3822271
revert $fields->lang in template links
darcywong00 Apr 6, 2026
a92ac18
fix keyboard landing page links
darcywong00 Apr 6, 2026
7965b0a
fix more landing links
darcywong00 Apr 6, 2026
5c1970b
try to fix more keyboard landing links
darcywong00 Apr 6, 2026
be580bd
fix: handle assets
darcywong00 Apr 6, 2026
224561f
fix ios links so they can be relative
darcywong00 Apr 7, 2026
948550f
revert _test/index.md changes
darcywong00 Apr 7, 2026
b37b468
fix: Use absolute paths for _test/ page
darcywong00 Apr 7, 2026
5dd6beb
fix: re-enable 404 pages
darcywong00 Apr 7, 2026
11c3a70
fixup cdn asset links
darcywong00 Apr 7, 2026
2440249
Apply suggestions from code review
darcywong00 Apr 8, 2026
7a434a0
fix: Convert android/iOS app links to root level redirect
darcywong00 Apr 8, 2026
2211c08
fix some links per review comments
darcywong00 Apr 8, 2026
c44bd72
fix: Move cdn rule to section with _control, go, _test
darcywong00 Apr 8, 2026
5531862
fix: Make windows archive link relative
darcywong00 Apr 8, 2026
490a0f5
fix RewriteCond for asset
darcywong00 Apr 8, 2026
3b78d44
Revert fields->lang to header and footer
darcywong00 Apr 8, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
247 changes: 164 additions & 83 deletions .htaccess
Original file line number Diff line number Diff line change
Expand Up @@ -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]

Expand All @@ -50,14 +86,7 @@ RedirectMatch 301 "^(?i)/privacy(\/.*)?" "https://software.sil.org/language-soft
# 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
# releases-download index
RewriteRule "^downloads/releases(\/)?$" "/downloads" [R,END]

# CLDR -> LDML
Expand Down Expand Up @@ -86,57 +115,12 @@ 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/<id>
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"

# Connect With Art landing page
RedirectMatch "/connectwithart(\/|$)" "https://sites.google.com/sil.org/connectwithart/home"

Expand Down Expand Up @@ -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 <lang>/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/<id>
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]

#
# PHP rewriting
# 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
#
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]
3 changes: 0 additions & 3 deletions _content/android/app/.htaccess

This file was deleted.

3 changes: 0 additions & 3 deletions _content/archive/.htaccess

This file was deleted.

6 changes: 3 additions & 3 deletions _content/developer/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,14 @@
?>

<h2 class="red underline">Keyman Developer <?php echo $stable_version_int; ?></h2>
<p><a href="features.php">Keyman Developer <?php echo $stable_version_int; ?></a> is the most powerful tool for creating
<p><a href="features">Keyman Developer <?php echo $stable_version_int; ?></a> 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.
</p>

<ul>
<li><a href="features.php">See the features.</a></li>
<li><a href='download.php'>Keyman Developer Downloads</a></li>
<li><a href="features">See the features.</a></li>
<li><a href='download'>Keyman Developer Downloads</a></li>
<li><a href='<?= KeymanHosts::Instance()->help_keyman_com ?>/developer/<?php echo $stable_version; ?>/'>Keyman Developer Support</a></li>
<li><a href='authoring-services'>Keyboard authoring service providers</a></li>
</ul>
Expand Down
10 changes: 5 additions & 5 deletions _content/developer/keymanweb/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<h2 class="red underline">KeymanWeb Source Code and Development</h2>
<p>
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 <a href='../download'>Keyman Developer</a> (Windows).
use with KeymanWeb can be created with the free download <a href='../download'>Keyman Developer</a> (Windows).
</p>

<h2 class="red underline">Add KeymanWeb to a Website</h2>
Expand All @@ -45,11 +45,11 @@

<ul>
<li>
<a href='sample1.php' target='_blank'>Basic Example</a>
<a href='sample1' target='_blank'>Basic Example</a>
(<a href="https://github.com/keymanapp/keyman.com/blob/master/developer/keymanweb/sample1.php">source code</a>)
</li>
<li>
<a href='sample2.php' target='_blank'>Multi-language example</a>
<a href='sample2' target='_blank'>Multi-language example</a>
(<a href="https://github.com/keymanapp/keyman.com/blob/master/developer/keymanweb/sample2.php">source code</a>)
</li>
</ul>
Expand Down Expand Up @@ -97,9 +97,9 @@
<br>

<ul>
<li><a href='keyboards.php'>Keyman Cloud CDN Keyboard Catalogue</a></li>
<li><a href='keyboards'>Keyman Cloud CDN Keyboard Catalogue</a></li>
<li><a href='<?= KeymanHosts::Instance()->help_keyman_com ?>/developer/cloud/version/2.0'>How to: retrieve the latest version of KeymanWeb from Keyman Cloud CDN</a></li>
<li><a href='index.2.0.php'>Using older versions of KeymanWeb</a></li>
<li><a href='index.2.0'>Using older versions of KeymanWeb</a></li>
</ul>

<br>
Expand Down
3 changes: 0 additions & 3 deletions _content/iphone-and-ipad/app/.htaccess

This file was deleted.

2 changes: 1 addition & 1 deletion _content/keyboards/h/amharic/index.php
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@
<li><a href="/keyboards/gff_gurage_legacy">Gurage Legacy</a></li>
<li><a href="/keyboards/gff_harari">Harari</a></li>
<li><a href="/keyboards/gff_tigre">Tigre</a></li>
<li><a href="../tigrigna/eritrean">Tigrigna (Eritrea)</a></li>
<li><a href="../tigrigna/eritrean">Tigrigna (Eritrea)</a></li>
<li><a href="../tigrigna/">Tigrigna (Ethiopia)</a></li>
</ul>
</p>
Expand Down
Loading
Loading