UNPKG

7.49 kBPlain TextView Raw
1import {IncomingMessage, ServerResponse} from "http";
2import * as UrlParser from 'url';
3
4const SUB_DIR = /^(\/(\w\w(_\w\w)?))(?:\/|$)/;
5const SUB_DOMAIN_PIPE_REGEX = /(?:^|_)(\w\w(?:_\w\w)?)_(?:b\-[mt]\-)?[0-9a-f]{24,25}_pipe/i;
6const SUB_DOMAIN_REGEX = /^(?:www\.)?(\w\w(?:_\w\w)?)\./i;
7
8export interface ExtendedRequest extends IncomingMessage {
9 originalUrl?: string;
10 // set this field if you want to force specific locale for Bablic
11 forceLocale?: string;
12 bablic?:{
13 locale: string;
14 proxied?: boolean;
15 }
16}
17
18export interface ExtendedResponse extends ServerResponse {
19 locals?: any;
20}
21
22export type Middleware = (req: IncomingMessage, res: ServerResponse, next: () => void) => void;
23
24export interface KeywordMapper {
25 [locale: string]:{
26 [keyword:string]: string
27 }
28}
29
30function getLocaleFromFolder(folderLocale, locales) {
31 var index = locales.indexOf(folderLocale);
32 if (index > -1)
33 return locales[index];
34 folderLocale = folderLocale.substr(0, 2);
35 for (var i = 0; i < locales.length; i++) {
36 if (locales[i].substr(0, 2) == folderLocale)
37 return locales[i];
38 }
39 return '';
40}
41
42
43export function getLocaleByURL(parsedUrl, locale_detection, localeConfigs, cookieLocale, siteDefaultLocale, detectedLocale, isProxy, explicitLocale, subDirBase, folders, locales) {
44 switch (locale_detection) {
45 case 'querystring':
46 if (parsedUrl.query && typeof(parsedUrl.query) == 'object')
47 return parsedUrl.query.locale;
48 var matches = /locale=([^&]+)/.exec(parsedUrl.query || '');
49 if (matches && matches.length == 2 && matches[1])
50 return matches[1];
51 return cookieLocale || detectedLocale || siteDefaultLocale;
52 case "subdomain":
53 var regex = isProxy ? SUB_DOMAIN_PIPE_REGEX : SUB_DOMAIN_REGEX;
54 var matches = regex.exec(parsedUrl.hostname);
55 if (matches && matches.length > 1 && matches[1])
56 return matches[1];
57 return siteDefaultLocale;
58 case "subdir":
59 var pathname = parsedUrl.pathname;
60 if (subDirBase)
61 pathname = pathname.replace(subDirBase, '');
62 var match = SUB_DIR.exec(pathname);
63 if (match) {
64 if (folders && locales && folders[match[2]])
65 return getLocaleFromFolder(folders[match[2]], locales) || siteDefaultLocale;
66 return match[2];
67 }
68 if (explicitLocale)
69 return explicitLocale;
70 if (cookieLocale)
71 return cookieLocale;
72 return detectedLocale || siteDefaultLocale;
73 case "tld":
74 var matches = /\.(\w\w)$/.exec(parsedUrl.hostname);
75 if (matches && matches.length > 1 && matches[1])
76 return matches[1];
77 return null;
78 case "custom":
79 var parseDomainRule = function (str) {
80 return RegExp((str + '').replace(/([.?+^$[\]\\(){}|-])/g, "\\$1").replace(/\*/g, '.*'), 'i');
81 };
82
83 for (var locale in localeConfigs) {
84 var urlPattern = localeConfigs[locale];
85 if (urlPattern && parseDomainRule(urlPattern).test(parsedUrl.href))
86 return locale;
87 }
88 return explicitLocale || siteDefaultLocale;
89 case "hash":
90 var matches = /^#!locale=(\w\w(?:_\w\w)?)$/.exec(parsedUrl.hash || '');
91 if (matches && matches.length > 1 && matches[1])
92 return matches[1];
93 return cookieLocale || detectedLocale || siteDefaultLocale;
94 default:
95 return cookieLocale;
96 }
97}
98export interface SiteMeta{
99 localeDetection: string;
100 original: string;
101 customUrls: {
102 [locale:string]:string
103 };
104 default: string;
105 autoDetect: boolean;
106 localeKeys: string[];
107 timestamp: number;
108 includeQueryString: boolean;
109 includeHash: boolean;
110 singlePageApp: boolean;
111 qsParams: string[],
112 domain: string;
113 mountSubs: string[];
114}
115
116
117export interface LastModifiedByLocale {
118 [locale: string]: Date
119}
120
121export interface BablicLinkOptions {
122 subDir?: boolean;
123 subDirBase?: string;
124 subDirOptional?: boolean;
125 returnFull?: boolean;
126 folders?:{[locale:string]:string}
127}
128
129export function getLink(locale: string, parsed: UrlParser.Url, meta: SiteMeta, options?: BablicLinkOptions) {
130 options = options || {};
131 let protocol = parsed.protocol || '';
132 let hostname = parsed.hostname;
133 let pathname = parsed.pathname || '/';
134 let search = parsed.search || '';
135 let hash = parsed.hash || '';
136
137 let returnFull = options.returnFull && !!hostname;
138 let localeDetection = meta.localeDetection;
139 let original = meta.original;
140 if(options.subDir)
141 localeDetection = 'subdir';
142 if(localeDetection == 'custom' && !(meta.customUrls && meta.customUrls[locale]))
143 localeDetection = 'querystring';
144
145 switch(localeDetection){
146 case 'custom':
147 let customUrl = meta.customUrls[locale];
148 let confDomain = customUrl.indexOf('/') > -1 ? customUrl.substr(0,customUrl.indexOf('/')) : customUrl;
149 return protocol + '//' + confDomain + pathname + search + hash;
150
151 case 'querystring':
152 if (/[?&]locale=([^&]+)/.test(search))
153 search = search.replace(/([?&]locale=)([^&]+)/, '$1' + locale);
154 else {
155 if (search)
156 search = search + '&locale=' + locale;
157 else
158 search = '?locale=' + locale;
159 }
160 if(returnFull)
161 return protocol + '//' + hostname + pathname + search + hash;
162
163 return pathname + search + hash;
164
165 case 'subdir':
166 if(options.subDirBase)
167 pathname = pathname.replace(options.subDirBase,'');
168 let match = SUB_DIR.exec(pathname);
169 if (match) {
170 pathname = pathname.substr(match[1].length);
171 if (pathname.length == 0)
172 pathname = '/';
173 }
174 let prefix = '';
175 if(options.folders)
176 prefix = '/' + getFolder(locale,options.folders);
177 else if(locale != original)
178 prefix = '/' + locale;
179 if(options.subDirBase && (!options.subDirOptional || locale != original))
180 prefix = options.subDirBase + prefix;
181 if(returnFull)
182 return protocol + '//' + hostname + prefix + pathname + search + hash;
183 return prefix + pathname + search + hash;
184 case 'hash':
185 if(returnFull)
186 return protocol + '//' + hostname + pathname + search + '#locale=' + locale;
187 return '#locale_' + locale;
188 }
189 return `javascript:bablic.setLanguage("${locale}");`;
190}
191
192
193function getFolder(locale: string,folders:{[locale:string]:string}) :string{
194 for(let folder in folders){
195 if(folders[folder] == locale)
196 return folder;
197 }
198 locale = locale.substr(0,2);
199 for(let folder in folders){
200 if(folders[folder].substr(0,2) == locale)
201 return folder;
202 }
203 return locale;
204}