@nocios/crudify-components 2.0.36 → 2.0.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/coverage/components/CrudiaAutoGenerate.tsx.html +583 -0
- package/coverage/components/CrudiaFileField/CrudiaFileField.tsx.html +1276 -0
- package/coverage/components/CrudiaFileField/components/DeleteConfirmationDialog.tsx.html +355 -0
- package/coverage/components/CrudiaFileField/components/DropZone.tsx.html +433 -0
- package/coverage/components/CrudiaFileField/components/FileItemRow.tsx.html +751 -0
- package/coverage/components/CrudiaFileField/components/FileThumbnail.tsx.html +1195 -0
- package/coverage/components/CrudiaFileField/components/index.html +176 -0
- package/coverage/components/CrudiaFileField/components/index.ts.html +115 -0
- package/coverage/components/CrudiaFileField/hooks/index.html +146 -0
- package/coverage/components/CrudiaFileField/hooks/index.ts.html +112 -0
- package/coverage/components/CrudiaFileField/hooks/useDeleteConfirmation.ts.html +421 -0
- package/coverage/components/CrudiaFileField/hooks/useDragDrop.ts.html +403 -0
- package/coverage/components/CrudiaFileField/index.html +131 -0
- package/coverage/components/CrudiaFileField/index.ts.html +112 -0
- package/coverage/components/CrudiaFileField/utils/formatters.ts.html +163 -0
- package/coverage/components/CrudiaFileField/utils/icons.tsx.html +253 -0
- package/coverage/components/CrudiaFileField/utils/index.html +131 -0
- package/coverage/components/CrudiaMarkdownField.tsx.html +619 -0
- package/coverage/components/CrudifyLogin/Forms/CheckCodeForm.tsx.html +586 -0
- package/coverage/components/CrudifyLogin/Forms/ForgotPasswordForm.tsx.html +694 -0
- package/coverage/components/CrudifyLogin/Forms/LoginForm.tsx.html +835 -0
- package/coverage/components/CrudifyLogin/Forms/ResetPasswordForm.tsx.html +1180 -0
- package/coverage/components/CrudifyLogin/Forms/components/CodeInput.tsx.html +283 -0
- package/coverage/components/CrudifyLogin/Forms/components/FormAlert.tsx.html +202 -0
- package/coverage/components/CrudifyLogin/Forms/components/PasswordInput.tsx.html +340 -0
- package/coverage/components/CrudifyLogin/Forms/components/index.html +161 -0
- package/coverage/components/CrudifyLogin/Forms/components/index.ts.html +106 -0
- package/coverage/components/CrudifyLogin/Forms/index.html +161 -0
- package/coverage/components/CrudifyLogin/Forms/utils/errorTranslation.ts.html +268 -0
- package/coverage/components/CrudifyLogin/Forms/utils/index.html +161 -0
- package/coverage/components/CrudifyLogin/Forms/utils/index.ts.html +106 -0
- package/coverage/components/CrudifyLogin/Forms/utils/paramUtils.ts.html +478 -0
- package/coverage/components/CrudifyLogin/Forms/utils/validation.ts.html +289 -0
- package/coverage/components/CrudifyLogin/components/CrudifyInitializer.tsx.html +262 -0
- package/coverage/components/CrudifyLogin/components/index.html +116 -0
- package/coverage/components/CrudifyLogin/context/CrudifyProvider.tsx.html +382 -0
- package/coverage/components/CrudifyLogin/context/I18nProvider.tsx.html +397 -0
- package/coverage/components/CrudifyLogin/context/LoginStateProvider.tsx.html +1249 -0
- package/coverage/components/CrudifyLogin/context/index.html +146 -0
- package/coverage/components/CrudifyLogin/hooks/index.html +116 -0
- package/coverage/components/CrudifyLogin/hooks/useTranslationsFromUrl.ts.html +292 -0
- package/coverage/components/CrudifyLogin/index.html +116 -0
- package/coverage/components/CrudifyLogin/index.tsx.html +475 -0
- package/coverage/components/GlobalNotificationProvider.tsx.html +781 -0
- package/coverage/components/LoginComponent.tsx.html +727 -0
- package/coverage/components/PasswordRequirements/index.html +116 -0
- package/coverage/components/PasswordRequirements/index.tsx.html +226 -0
- package/coverage/components/PublicPolicies/FieldSelector/FieldSelector.tsx.html +982 -0
- package/coverage/components/PublicPolicies/FieldSelector/index.html +131 -0
- package/coverage/components/PublicPolicies/FieldSelector/index.ts.html +85 -0
- package/coverage/components/PublicPolicies/Policies.tsx.html +610 -0
- package/coverage/components/PublicPolicies/PolicyItem/PolicyItem.tsx.html +856 -0
- package/coverage/components/PublicPolicies/PolicyItem/index.html +131 -0
- package/coverage/components/PublicPolicies/PolicyItem/index.ts.html +85 -0
- package/coverage/components/PublicPolicies/constants.ts.html +127 -0
- package/coverage/components/PublicPolicies/index.html +131 -0
- package/coverage/components/SessionTimeIndicator/index.html +116 -0
- package/coverage/components/SessionTimeIndicator/index.tsx.html +505 -0
- package/coverage/components/UserProfile/UserProfileDisplay.tsx.html +826 -0
- package/coverage/components/UserProfile/index.html +131 -0
- package/coverage/components/UserProfile/index.ts.html +85 -0
- package/coverage/components/index.html +176 -0
- package/coverage/components/index.ts.html +160 -0
- package/coverage/core/CrossTabSyncManager.ts.html +814 -0
- package/coverage/core/CrudifyInitializationManager.ts.html +1132 -0
- package/coverage/core/SessionManager.ts.html +2764 -0
- package/coverage/core/index.html +146 -0
- package/coverage/coverage-final.json +52 -85
- package/coverage/hooks/index.html +131 -0
- package/coverage/hooks/useAutoGenerate.ts.html +562 -0
- package/coverage/hooks/useFileUpload/index.html +131 -0
- package/coverage/hooks/useFileUpload/index.ts.html +112 -0
- package/coverage/hooks/useFileUpload/services/index.html +116 -0
- package/coverage/hooks/useFileUpload/services/uploadService.ts.html +610 -0
- package/coverage/hooks/useFileUpload/useFileUpload.ts.html +1870 -0
- package/coverage/hooks/useFileUpload/utils/fileUtils.ts.html +271 -0
- package/coverage/hooks/useFileUpload/utils/index.html +146 -0
- package/coverage/hooks/useFileUpload/utils/mimeTypes.ts.html +235 -0
- package/coverage/hooks/useFileUpload/utils/validation.ts.html +379 -0
- package/coverage/hooks/useSession/constants.ts.html +217 -0
- package/coverage/hooks/useSession/hooks/index.html +176 -0
- package/coverage/hooks/useSession/hooks/useAuthEventSubscriber.ts.html +331 -0
- package/coverage/hooks/useSession/hooks/useCrossTabSync.ts.html +433 -0
- package/coverage/hooks/useSession/hooks/useSessionActions.ts.html +664 -0
- package/coverage/hooks/useSession/hooks/useSessionState.ts.html +295 -0
- package/coverage/hooks/useSession/hooks/useTokenRefreshScheduler.ts.html +490 -0
- package/coverage/hooks/useSession/index.html +161 -0
- package/coverage/hooks/useSession/index.ts.html +127 -0
- package/coverage/hooks/useSession/types.ts.html +427 -0
- package/coverage/hooks/useSession/useSession.ts.html +526 -0
- package/coverage/hooks/useSession/utils/index.html +131 -0
- package/coverage/hooks/useSession/utils/initializeSession.ts.html +424 -0
- package/coverage/hooks/useSession/utils/tokenUtils.ts.html +280 -0
- package/coverage/hooks/useUserProfile.ts.html +658 -0
- package/coverage/index.html +237 -357
- package/coverage/providers/SessionProvider.tsx.html +1150 -0
- package/coverage/providers/TranslationsProvider.tsx.html +1450 -0
- package/coverage/providers/index.html +131 -0
- package/coverage/services/credentialsEventBus.ts.html +310 -0
- package/coverage/services/index.html +131 -0
- package/coverage/services/translationService.ts.html +1318 -0
- package/coverage/translations/critical.ts.html +1195 -0
- package/coverage/translations/index.html +116 -0
- package/coverage/types/index.html +116 -0
- package/coverage/types/password.ts.html +178 -0
- package/coverage/utils/authEventBus.ts.html +454 -0
- package/coverage/utils/configResolver.ts.html +460 -0
- package/coverage/utils/cookieSync.ts.html +580 -0
- package/coverage/utils/errorHandler.ts.html +1264 -0
- package/coverage/utils/errorTranslation.ts.html +862 -0
- package/coverage/utils/index.html +296 -0
- package/coverage/utils/jwtUtils.ts.html +301 -0
- package/coverage/utils/logger.ts.html +901 -0
- package/coverage/utils/navigationTracker.ts.html +565 -0
- package/coverage/utils/passwordValidation.ts.html +259 -0
- package/coverage/utils/redirectSecurity.ts.html +715 -0
- package/coverage/utils/tenantConfig.ts.html +700 -0
- package/coverage/utils/tokenStorage.ts.html +1768 -0
- package/coverage/utils/webCrypto.ts.html +472 -0
- package/dist/{CrudiaMarkdownField-Bxl08sRG.d.mts → CrudiaMarkdownField-BvJn2GL8.d.mts} +5 -0
- package/dist/{CrudiaMarkdownField-DUJNOOzP.d.ts → CrudiaMarkdownField-CggOpcBM.d.ts} +5 -0
- package/dist/chunk-SYHNHKFA.mjs +1 -0
- package/dist/chunk-W4ZYKPOK.js +1 -0
- package/dist/components.d.mts +1 -1
- package/dist/components.d.ts +1 -1
- package/dist/components.js +1 -1
- package/dist/components.mjs +1 -1
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +2 -2
- package/dist/index.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-QFACMV2I.mjs +0 -1
- package/dist/chunk-QZH3KSJZ.js +0 -1
|
@@ -0,0 +1,1450 @@
|
|
|
1
|
+
|
|
2
|
+
<!doctype html>
|
|
3
|
+
<html lang="en">
|
|
4
|
+
|
|
5
|
+
<head>
|
|
6
|
+
<title>Code coverage report for providers/TranslationsProvider.tsx</title>
|
|
7
|
+
<meta charset="utf-8" />
|
|
8
|
+
<link rel="stylesheet" href="../prettify.css" />
|
|
9
|
+
<link rel="stylesheet" href="../base.css" />
|
|
10
|
+
<link rel="shortcut icon" type="image/x-icon" href="../favicon.png" />
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
+
<style type='text/css'>
|
|
13
|
+
.coverage-summary .sorter {
|
|
14
|
+
background-image: url(../sort-arrow-sprite.png);
|
|
15
|
+
}
|
|
16
|
+
</style>
|
|
17
|
+
</head>
|
|
18
|
+
|
|
19
|
+
<body>
|
|
20
|
+
<div class='wrapper'>
|
|
21
|
+
<div class='pad1'>
|
|
22
|
+
<h1><a href="../index.html">All files</a> / <a href="index.html">providers</a> TranslationsProvider.tsx</h1>
|
|
23
|
+
<div class='clearfix'>
|
|
24
|
+
|
|
25
|
+
<div class='fl pad1y space-right2'>
|
|
26
|
+
<span class="strong">85.27% </span>
|
|
27
|
+
<span class="quiet">Statements</span>
|
|
28
|
+
<span class='fraction'>388/455</span>
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<div class='fl pad1y space-right2'>
|
|
33
|
+
<span class="strong">69.44% </span>
|
|
34
|
+
<span class="quiet">Branches</span>
|
|
35
|
+
<span class='fraction'>50/72</span>
|
|
36
|
+
</div>
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
<div class='fl pad1y space-right2'>
|
|
40
|
+
<span class="strong">100% </span>
|
|
41
|
+
<span class="quiet">Functions</span>
|
|
42
|
+
<span class='fraction'>4/4</span>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<div class='fl pad1y space-right2'>
|
|
47
|
+
<span class="strong">85.27% </span>
|
|
48
|
+
<span class="quiet">Lines</span>
|
|
49
|
+
<span class='fraction'>388/455</span>
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
<p class="quiet">
|
|
55
|
+
Press <em>n</em> or <em>j</em> to go to the next uncovered block, <em>b</em>, <em>p</em> or <em>k</em> for the previous block.
|
|
56
|
+
</p>
|
|
57
|
+
<template id="filterTemplate">
|
|
58
|
+
<div class="quiet">
|
|
59
|
+
Filter:
|
|
60
|
+
<input type="search" id="fileSearch">
|
|
61
|
+
</div>
|
|
62
|
+
</template>
|
|
63
|
+
</div>
|
|
64
|
+
<div class='status-line high'></div>
|
|
65
|
+
<pre><table class="coverage">
|
|
66
|
+
<tr><td class="line-count quiet"><a name='L1'></a><a href='#L1'>1</a>
|
|
67
|
+
<a name='L2'></a><a href='#L2'>2</a>
|
|
68
|
+
<a name='L3'></a><a href='#L3'>3</a>
|
|
69
|
+
<a name='L4'></a><a href='#L4'>4</a>
|
|
70
|
+
<a name='L5'></a><a href='#L5'>5</a>
|
|
71
|
+
<a name='L6'></a><a href='#L6'>6</a>
|
|
72
|
+
<a name='L7'></a><a href='#L7'>7</a>
|
|
73
|
+
<a name='L8'></a><a href='#L8'>8</a>
|
|
74
|
+
<a name='L9'></a><a href='#L9'>9</a>
|
|
75
|
+
<a name='L10'></a><a href='#L10'>10</a>
|
|
76
|
+
<a name='L11'></a><a href='#L11'>11</a>
|
|
77
|
+
<a name='L12'></a><a href='#L12'>12</a>
|
|
78
|
+
<a name='L13'></a><a href='#L13'>13</a>
|
|
79
|
+
<a name='L14'></a><a href='#L14'>14</a>
|
|
80
|
+
<a name='L15'></a><a href='#L15'>15</a>
|
|
81
|
+
<a name='L16'></a><a href='#L16'>16</a>
|
|
82
|
+
<a name='L17'></a><a href='#L17'>17</a>
|
|
83
|
+
<a name='L18'></a><a href='#L18'>18</a>
|
|
84
|
+
<a name='L19'></a><a href='#L19'>19</a>
|
|
85
|
+
<a name='L20'></a><a href='#L20'>20</a>
|
|
86
|
+
<a name='L21'></a><a href='#L21'>21</a>
|
|
87
|
+
<a name='L22'></a><a href='#L22'>22</a>
|
|
88
|
+
<a name='L23'></a><a href='#L23'>23</a>
|
|
89
|
+
<a name='L24'></a><a href='#L24'>24</a>
|
|
90
|
+
<a name='L25'></a><a href='#L25'>25</a>
|
|
91
|
+
<a name='L26'></a><a href='#L26'>26</a>
|
|
92
|
+
<a name='L27'></a><a href='#L27'>27</a>
|
|
93
|
+
<a name='L28'></a><a href='#L28'>28</a>
|
|
94
|
+
<a name='L29'></a><a href='#L29'>29</a>
|
|
95
|
+
<a name='L30'></a><a href='#L30'>30</a>
|
|
96
|
+
<a name='L31'></a><a href='#L31'>31</a>
|
|
97
|
+
<a name='L32'></a><a href='#L32'>32</a>
|
|
98
|
+
<a name='L33'></a><a href='#L33'>33</a>
|
|
99
|
+
<a name='L34'></a><a href='#L34'>34</a>
|
|
100
|
+
<a name='L35'></a><a href='#L35'>35</a>
|
|
101
|
+
<a name='L36'></a><a href='#L36'>36</a>
|
|
102
|
+
<a name='L37'></a><a href='#L37'>37</a>
|
|
103
|
+
<a name='L38'></a><a href='#L38'>38</a>
|
|
104
|
+
<a name='L39'></a><a href='#L39'>39</a>
|
|
105
|
+
<a name='L40'></a><a href='#L40'>40</a>
|
|
106
|
+
<a name='L41'></a><a href='#L41'>41</a>
|
|
107
|
+
<a name='L42'></a><a href='#L42'>42</a>
|
|
108
|
+
<a name='L43'></a><a href='#L43'>43</a>
|
|
109
|
+
<a name='L44'></a><a href='#L44'>44</a>
|
|
110
|
+
<a name='L45'></a><a href='#L45'>45</a>
|
|
111
|
+
<a name='L46'></a><a href='#L46'>46</a>
|
|
112
|
+
<a name='L47'></a><a href='#L47'>47</a>
|
|
113
|
+
<a name='L48'></a><a href='#L48'>48</a>
|
|
114
|
+
<a name='L49'></a><a href='#L49'>49</a>
|
|
115
|
+
<a name='L50'></a><a href='#L50'>50</a>
|
|
116
|
+
<a name='L51'></a><a href='#L51'>51</a>
|
|
117
|
+
<a name='L52'></a><a href='#L52'>52</a>
|
|
118
|
+
<a name='L53'></a><a href='#L53'>53</a>
|
|
119
|
+
<a name='L54'></a><a href='#L54'>54</a>
|
|
120
|
+
<a name='L55'></a><a href='#L55'>55</a>
|
|
121
|
+
<a name='L56'></a><a href='#L56'>56</a>
|
|
122
|
+
<a name='L57'></a><a href='#L57'>57</a>
|
|
123
|
+
<a name='L58'></a><a href='#L58'>58</a>
|
|
124
|
+
<a name='L59'></a><a href='#L59'>59</a>
|
|
125
|
+
<a name='L60'></a><a href='#L60'>60</a>
|
|
126
|
+
<a name='L61'></a><a href='#L61'>61</a>
|
|
127
|
+
<a name='L62'></a><a href='#L62'>62</a>
|
|
128
|
+
<a name='L63'></a><a href='#L63'>63</a>
|
|
129
|
+
<a name='L64'></a><a href='#L64'>64</a>
|
|
130
|
+
<a name='L65'></a><a href='#L65'>65</a>
|
|
131
|
+
<a name='L66'></a><a href='#L66'>66</a>
|
|
132
|
+
<a name='L67'></a><a href='#L67'>67</a>
|
|
133
|
+
<a name='L68'></a><a href='#L68'>68</a>
|
|
134
|
+
<a name='L69'></a><a href='#L69'>69</a>
|
|
135
|
+
<a name='L70'></a><a href='#L70'>70</a>
|
|
136
|
+
<a name='L71'></a><a href='#L71'>71</a>
|
|
137
|
+
<a name='L72'></a><a href='#L72'>72</a>
|
|
138
|
+
<a name='L73'></a><a href='#L73'>73</a>
|
|
139
|
+
<a name='L74'></a><a href='#L74'>74</a>
|
|
140
|
+
<a name='L75'></a><a href='#L75'>75</a>
|
|
141
|
+
<a name='L76'></a><a href='#L76'>76</a>
|
|
142
|
+
<a name='L77'></a><a href='#L77'>77</a>
|
|
143
|
+
<a name='L78'></a><a href='#L78'>78</a>
|
|
144
|
+
<a name='L79'></a><a href='#L79'>79</a>
|
|
145
|
+
<a name='L80'></a><a href='#L80'>80</a>
|
|
146
|
+
<a name='L81'></a><a href='#L81'>81</a>
|
|
147
|
+
<a name='L82'></a><a href='#L82'>82</a>
|
|
148
|
+
<a name='L83'></a><a href='#L83'>83</a>
|
|
149
|
+
<a name='L84'></a><a href='#L84'>84</a>
|
|
150
|
+
<a name='L85'></a><a href='#L85'>85</a>
|
|
151
|
+
<a name='L86'></a><a href='#L86'>86</a>
|
|
152
|
+
<a name='L87'></a><a href='#L87'>87</a>
|
|
153
|
+
<a name='L88'></a><a href='#L88'>88</a>
|
|
154
|
+
<a name='L89'></a><a href='#L89'>89</a>
|
|
155
|
+
<a name='L90'></a><a href='#L90'>90</a>
|
|
156
|
+
<a name='L91'></a><a href='#L91'>91</a>
|
|
157
|
+
<a name='L92'></a><a href='#L92'>92</a>
|
|
158
|
+
<a name='L93'></a><a href='#L93'>93</a>
|
|
159
|
+
<a name='L94'></a><a href='#L94'>94</a>
|
|
160
|
+
<a name='L95'></a><a href='#L95'>95</a>
|
|
161
|
+
<a name='L96'></a><a href='#L96'>96</a>
|
|
162
|
+
<a name='L97'></a><a href='#L97'>97</a>
|
|
163
|
+
<a name='L98'></a><a href='#L98'>98</a>
|
|
164
|
+
<a name='L99'></a><a href='#L99'>99</a>
|
|
165
|
+
<a name='L100'></a><a href='#L100'>100</a>
|
|
166
|
+
<a name='L101'></a><a href='#L101'>101</a>
|
|
167
|
+
<a name='L102'></a><a href='#L102'>102</a>
|
|
168
|
+
<a name='L103'></a><a href='#L103'>103</a>
|
|
169
|
+
<a name='L104'></a><a href='#L104'>104</a>
|
|
170
|
+
<a name='L105'></a><a href='#L105'>105</a>
|
|
171
|
+
<a name='L106'></a><a href='#L106'>106</a>
|
|
172
|
+
<a name='L107'></a><a href='#L107'>107</a>
|
|
173
|
+
<a name='L108'></a><a href='#L108'>108</a>
|
|
174
|
+
<a name='L109'></a><a href='#L109'>109</a>
|
|
175
|
+
<a name='L110'></a><a href='#L110'>110</a>
|
|
176
|
+
<a name='L111'></a><a href='#L111'>111</a>
|
|
177
|
+
<a name='L112'></a><a href='#L112'>112</a>
|
|
178
|
+
<a name='L113'></a><a href='#L113'>113</a>
|
|
179
|
+
<a name='L114'></a><a href='#L114'>114</a>
|
|
180
|
+
<a name='L115'></a><a href='#L115'>115</a>
|
|
181
|
+
<a name='L116'></a><a href='#L116'>116</a>
|
|
182
|
+
<a name='L117'></a><a href='#L117'>117</a>
|
|
183
|
+
<a name='L118'></a><a href='#L118'>118</a>
|
|
184
|
+
<a name='L119'></a><a href='#L119'>119</a>
|
|
185
|
+
<a name='L120'></a><a href='#L120'>120</a>
|
|
186
|
+
<a name='L121'></a><a href='#L121'>121</a>
|
|
187
|
+
<a name='L122'></a><a href='#L122'>122</a>
|
|
188
|
+
<a name='L123'></a><a href='#L123'>123</a>
|
|
189
|
+
<a name='L124'></a><a href='#L124'>124</a>
|
|
190
|
+
<a name='L125'></a><a href='#L125'>125</a>
|
|
191
|
+
<a name='L126'></a><a href='#L126'>126</a>
|
|
192
|
+
<a name='L127'></a><a href='#L127'>127</a>
|
|
193
|
+
<a name='L128'></a><a href='#L128'>128</a>
|
|
194
|
+
<a name='L129'></a><a href='#L129'>129</a>
|
|
195
|
+
<a name='L130'></a><a href='#L130'>130</a>
|
|
196
|
+
<a name='L131'></a><a href='#L131'>131</a>
|
|
197
|
+
<a name='L132'></a><a href='#L132'>132</a>
|
|
198
|
+
<a name='L133'></a><a href='#L133'>133</a>
|
|
199
|
+
<a name='L134'></a><a href='#L134'>134</a>
|
|
200
|
+
<a name='L135'></a><a href='#L135'>135</a>
|
|
201
|
+
<a name='L136'></a><a href='#L136'>136</a>
|
|
202
|
+
<a name='L137'></a><a href='#L137'>137</a>
|
|
203
|
+
<a name='L138'></a><a href='#L138'>138</a>
|
|
204
|
+
<a name='L139'></a><a href='#L139'>139</a>
|
|
205
|
+
<a name='L140'></a><a href='#L140'>140</a>
|
|
206
|
+
<a name='L141'></a><a href='#L141'>141</a>
|
|
207
|
+
<a name='L142'></a><a href='#L142'>142</a>
|
|
208
|
+
<a name='L143'></a><a href='#L143'>143</a>
|
|
209
|
+
<a name='L144'></a><a href='#L144'>144</a>
|
|
210
|
+
<a name='L145'></a><a href='#L145'>145</a>
|
|
211
|
+
<a name='L146'></a><a href='#L146'>146</a>
|
|
212
|
+
<a name='L147'></a><a href='#L147'>147</a>
|
|
213
|
+
<a name='L148'></a><a href='#L148'>148</a>
|
|
214
|
+
<a name='L149'></a><a href='#L149'>149</a>
|
|
215
|
+
<a name='L150'></a><a href='#L150'>150</a>
|
|
216
|
+
<a name='L151'></a><a href='#L151'>151</a>
|
|
217
|
+
<a name='L152'></a><a href='#L152'>152</a>
|
|
218
|
+
<a name='L153'></a><a href='#L153'>153</a>
|
|
219
|
+
<a name='L154'></a><a href='#L154'>154</a>
|
|
220
|
+
<a name='L155'></a><a href='#L155'>155</a>
|
|
221
|
+
<a name='L156'></a><a href='#L156'>156</a>
|
|
222
|
+
<a name='L157'></a><a href='#L157'>157</a>
|
|
223
|
+
<a name='L158'></a><a href='#L158'>158</a>
|
|
224
|
+
<a name='L159'></a><a href='#L159'>159</a>
|
|
225
|
+
<a name='L160'></a><a href='#L160'>160</a>
|
|
226
|
+
<a name='L161'></a><a href='#L161'>161</a>
|
|
227
|
+
<a name='L162'></a><a href='#L162'>162</a>
|
|
228
|
+
<a name='L163'></a><a href='#L163'>163</a>
|
|
229
|
+
<a name='L164'></a><a href='#L164'>164</a>
|
|
230
|
+
<a name='L165'></a><a href='#L165'>165</a>
|
|
231
|
+
<a name='L166'></a><a href='#L166'>166</a>
|
|
232
|
+
<a name='L167'></a><a href='#L167'>167</a>
|
|
233
|
+
<a name='L168'></a><a href='#L168'>168</a>
|
|
234
|
+
<a name='L169'></a><a href='#L169'>169</a>
|
|
235
|
+
<a name='L170'></a><a href='#L170'>170</a>
|
|
236
|
+
<a name='L171'></a><a href='#L171'>171</a>
|
|
237
|
+
<a name='L172'></a><a href='#L172'>172</a>
|
|
238
|
+
<a name='L173'></a><a href='#L173'>173</a>
|
|
239
|
+
<a name='L174'></a><a href='#L174'>174</a>
|
|
240
|
+
<a name='L175'></a><a href='#L175'>175</a>
|
|
241
|
+
<a name='L176'></a><a href='#L176'>176</a>
|
|
242
|
+
<a name='L177'></a><a href='#L177'>177</a>
|
|
243
|
+
<a name='L178'></a><a href='#L178'>178</a>
|
|
244
|
+
<a name='L179'></a><a href='#L179'>179</a>
|
|
245
|
+
<a name='L180'></a><a href='#L180'>180</a>
|
|
246
|
+
<a name='L181'></a><a href='#L181'>181</a>
|
|
247
|
+
<a name='L182'></a><a href='#L182'>182</a>
|
|
248
|
+
<a name='L183'></a><a href='#L183'>183</a>
|
|
249
|
+
<a name='L184'></a><a href='#L184'>184</a>
|
|
250
|
+
<a name='L185'></a><a href='#L185'>185</a>
|
|
251
|
+
<a name='L186'></a><a href='#L186'>186</a>
|
|
252
|
+
<a name='L187'></a><a href='#L187'>187</a>
|
|
253
|
+
<a name='L188'></a><a href='#L188'>188</a>
|
|
254
|
+
<a name='L189'></a><a href='#L189'>189</a>
|
|
255
|
+
<a name='L190'></a><a href='#L190'>190</a>
|
|
256
|
+
<a name='L191'></a><a href='#L191'>191</a>
|
|
257
|
+
<a name='L192'></a><a href='#L192'>192</a>
|
|
258
|
+
<a name='L193'></a><a href='#L193'>193</a>
|
|
259
|
+
<a name='L194'></a><a href='#L194'>194</a>
|
|
260
|
+
<a name='L195'></a><a href='#L195'>195</a>
|
|
261
|
+
<a name='L196'></a><a href='#L196'>196</a>
|
|
262
|
+
<a name='L197'></a><a href='#L197'>197</a>
|
|
263
|
+
<a name='L198'></a><a href='#L198'>198</a>
|
|
264
|
+
<a name='L199'></a><a href='#L199'>199</a>
|
|
265
|
+
<a name='L200'></a><a href='#L200'>200</a>
|
|
266
|
+
<a name='L201'></a><a href='#L201'>201</a>
|
|
267
|
+
<a name='L202'></a><a href='#L202'>202</a>
|
|
268
|
+
<a name='L203'></a><a href='#L203'>203</a>
|
|
269
|
+
<a name='L204'></a><a href='#L204'>204</a>
|
|
270
|
+
<a name='L205'></a><a href='#L205'>205</a>
|
|
271
|
+
<a name='L206'></a><a href='#L206'>206</a>
|
|
272
|
+
<a name='L207'></a><a href='#L207'>207</a>
|
|
273
|
+
<a name='L208'></a><a href='#L208'>208</a>
|
|
274
|
+
<a name='L209'></a><a href='#L209'>209</a>
|
|
275
|
+
<a name='L210'></a><a href='#L210'>210</a>
|
|
276
|
+
<a name='L211'></a><a href='#L211'>211</a>
|
|
277
|
+
<a name='L212'></a><a href='#L212'>212</a>
|
|
278
|
+
<a name='L213'></a><a href='#L213'>213</a>
|
|
279
|
+
<a name='L214'></a><a href='#L214'>214</a>
|
|
280
|
+
<a name='L215'></a><a href='#L215'>215</a>
|
|
281
|
+
<a name='L216'></a><a href='#L216'>216</a>
|
|
282
|
+
<a name='L217'></a><a href='#L217'>217</a>
|
|
283
|
+
<a name='L218'></a><a href='#L218'>218</a>
|
|
284
|
+
<a name='L219'></a><a href='#L219'>219</a>
|
|
285
|
+
<a name='L220'></a><a href='#L220'>220</a>
|
|
286
|
+
<a name='L221'></a><a href='#L221'>221</a>
|
|
287
|
+
<a name='L222'></a><a href='#L222'>222</a>
|
|
288
|
+
<a name='L223'></a><a href='#L223'>223</a>
|
|
289
|
+
<a name='L224'></a><a href='#L224'>224</a>
|
|
290
|
+
<a name='L225'></a><a href='#L225'>225</a>
|
|
291
|
+
<a name='L226'></a><a href='#L226'>226</a>
|
|
292
|
+
<a name='L227'></a><a href='#L227'>227</a>
|
|
293
|
+
<a name='L228'></a><a href='#L228'>228</a>
|
|
294
|
+
<a name='L229'></a><a href='#L229'>229</a>
|
|
295
|
+
<a name='L230'></a><a href='#L230'>230</a>
|
|
296
|
+
<a name='L231'></a><a href='#L231'>231</a>
|
|
297
|
+
<a name='L232'></a><a href='#L232'>232</a>
|
|
298
|
+
<a name='L233'></a><a href='#L233'>233</a>
|
|
299
|
+
<a name='L234'></a><a href='#L234'>234</a>
|
|
300
|
+
<a name='L235'></a><a href='#L235'>235</a>
|
|
301
|
+
<a name='L236'></a><a href='#L236'>236</a>
|
|
302
|
+
<a name='L237'></a><a href='#L237'>237</a>
|
|
303
|
+
<a name='L238'></a><a href='#L238'>238</a>
|
|
304
|
+
<a name='L239'></a><a href='#L239'>239</a>
|
|
305
|
+
<a name='L240'></a><a href='#L240'>240</a>
|
|
306
|
+
<a name='L241'></a><a href='#L241'>241</a>
|
|
307
|
+
<a name='L242'></a><a href='#L242'>242</a>
|
|
308
|
+
<a name='L243'></a><a href='#L243'>243</a>
|
|
309
|
+
<a name='L244'></a><a href='#L244'>244</a>
|
|
310
|
+
<a name='L245'></a><a href='#L245'>245</a>
|
|
311
|
+
<a name='L246'></a><a href='#L246'>246</a>
|
|
312
|
+
<a name='L247'></a><a href='#L247'>247</a>
|
|
313
|
+
<a name='L248'></a><a href='#L248'>248</a>
|
|
314
|
+
<a name='L249'></a><a href='#L249'>249</a>
|
|
315
|
+
<a name='L250'></a><a href='#L250'>250</a>
|
|
316
|
+
<a name='L251'></a><a href='#L251'>251</a>
|
|
317
|
+
<a name='L252'></a><a href='#L252'>252</a>
|
|
318
|
+
<a name='L253'></a><a href='#L253'>253</a>
|
|
319
|
+
<a name='L254'></a><a href='#L254'>254</a>
|
|
320
|
+
<a name='L255'></a><a href='#L255'>255</a>
|
|
321
|
+
<a name='L256'></a><a href='#L256'>256</a>
|
|
322
|
+
<a name='L257'></a><a href='#L257'>257</a>
|
|
323
|
+
<a name='L258'></a><a href='#L258'>258</a>
|
|
324
|
+
<a name='L259'></a><a href='#L259'>259</a>
|
|
325
|
+
<a name='L260'></a><a href='#L260'>260</a>
|
|
326
|
+
<a name='L261'></a><a href='#L261'>261</a>
|
|
327
|
+
<a name='L262'></a><a href='#L262'>262</a>
|
|
328
|
+
<a name='L263'></a><a href='#L263'>263</a>
|
|
329
|
+
<a name='L264'></a><a href='#L264'>264</a>
|
|
330
|
+
<a name='L265'></a><a href='#L265'>265</a>
|
|
331
|
+
<a name='L266'></a><a href='#L266'>266</a>
|
|
332
|
+
<a name='L267'></a><a href='#L267'>267</a>
|
|
333
|
+
<a name='L268'></a><a href='#L268'>268</a>
|
|
334
|
+
<a name='L269'></a><a href='#L269'>269</a>
|
|
335
|
+
<a name='L270'></a><a href='#L270'>270</a>
|
|
336
|
+
<a name='L271'></a><a href='#L271'>271</a>
|
|
337
|
+
<a name='L272'></a><a href='#L272'>272</a>
|
|
338
|
+
<a name='L273'></a><a href='#L273'>273</a>
|
|
339
|
+
<a name='L274'></a><a href='#L274'>274</a>
|
|
340
|
+
<a name='L275'></a><a href='#L275'>275</a>
|
|
341
|
+
<a name='L276'></a><a href='#L276'>276</a>
|
|
342
|
+
<a name='L277'></a><a href='#L277'>277</a>
|
|
343
|
+
<a name='L278'></a><a href='#L278'>278</a>
|
|
344
|
+
<a name='L279'></a><a href='#L279'>279</a>
|
|
345
|
+
<a name='L280'></a><a href='#L280'>280</a>
|
|
346
|
+
<a name='L281'></a><a href='#L281'>281</a>
|
|
347
|
+
<a name='L282'></a><a href='#L282'>282</a>
|
|
348
|
+
<a name='L283'></a><a href='#L283'>283</a>
|
|
349
|
+
<a name='L284'></a><a href='#L284'>284</a>
|
|
350
|
+
<a name='L285'></a><a href='#L285'>285</a>
|
|
351
|
+
<a name='L286'></a><a href='#L286'>286</a>
|
|
352
|
+
<a name='L287'></a><a href='#L287'>287</a>
|
|
353
|
+
<a name='L288'></a><a href='#L288'>288</a>
|
|
354
|
+
<a name='L289'></a><a href='#L289'>289</a>
|
|
355
|
+
<a name='L290'></a><a href='#L290'>290</a>
|
|
356
|
+
<a name='L291'></a><a href='#L291'>291</a>
|
|
357
|
+
<a name='L292'></a><a href='#L292'>292</a>
|
|
358
|
+
<a name='L293'></a><a href='#L293'>293</a>
|
|
359
|
+
<a name='L294'></a><a href='#L294'>294</a>
|
|
360
|
+
<a name='L295'></a><a href='#L295'>295</a>
|
|
361
|
+
<a name='L296'></a><a href='#L296'>296</a>
|
|
362
|
+
<a name='L297'></a><a href='#L297'>297</a>
|
|
363
|
+
<a name='L298'></a><a href='#L298'>298</a>
|
|
364
|
+
<a name='L299'></a><a href='#L299'>299</a>
|
|
365
|
+
<a name='L300'></a><a href='#L300'>300</a>
|
|
366
|
+
<a name='L301'></a><a href='#L301'>301</a>
|
|
367
|
+
<a name='L302'></a><a href='#L302'>302</a>
|
|
368
|
+
<a name='L303'></a><a href='#L303'>303</a>
|
|
369
|
+
<a name='L304'></a><a href='#L304'>304</a>
|
|
370
|
+
<a name='L305'></a><a href='#L305'>305</a>
|
|
371
|
+
<a name='L306'></a><a href='#L306'>306</a>
|
|
372
|
+
<a name='L307'></a><a href='#L307'>307</a>
|
|
373
|
+
<a name='L308'></a><a href='#L308'>308</a>
|
|
374
|
+
<a name='L309'></a><a href='#L309'>309</a>
|
|
375
|
+
<a name='L310'></a><a href='#L310'>310</a>
|
|
376
|
+
<a name='L311'></a><a href='#L311'>311</a>
|
|
377
|
+
<a name='L312'></a><a href='#L312'>312</a>
|
|
378
|
+
<a name='L313'></a><a href='#L313'>313</a>
|
|
379
|
+
<a name='L314'></a><a href='#L314'>314</a>
|
|
380
|
+
<a name='L315'></a><a href='#L315'>315</a>
|
|
381
|
+
<a name='L316'></a><a href='#L316'>316</a>
|
|
382
|
+
<a name='L317'></a><a href='#L317'>317</a>
|
|
383
|
+
<a name='L318'></a><a href='#L318'>318</a>
|
|
384
|
+
<a name='L319'></a><a href='#L319'>319</a>
|
|
385
|
+
<a name='L320'></a><a href='#L320'>320</a>
|
|
386
|
+
<a name='L321'></a><a href='#L321'>321</a>
|
|
387
|
+
<a name='L322'></a><a href='#L322'>322</a>
|
|
388
|
+
<a name='L323'></a><a href='#L323'>323</a>
|
|
389
|
+
<a name='L324'></a><a href='#L324'>324</a>
|
|
390
|
+
<a name='L325'></a><a href='#L325'>325</a>
|
|
391
|
+
<a name='L326'></a><a href='#L326'>326</a>
|
|
392
|
+
<a name='L327'></a><a href='#L327'>327</a>
|
|
393
|
+
<a name='L328'></a><a href='#L328'>328</a>
|
|
394
|
+
<a name='L329'></a><a href='#L329'>329</a>
|
|
395
|
+
<a name='L330'></a><a href='#L330'>330</a>
|
|
396
|
+
<a name='L331'></a><a href='#L331'>331</a>
|
|
397
|
+
<a name='L332'></a><a href='#L332'>332</a>
|
|
398
|
+
<a name='L333'></a><a href='#L333'>333</a>
|
|
399
|
+
<a name='L334'></a><a href='#L334'>334</a>
|
|
400
|
+
<a name='L335'></a><a href='#L335'>335</a>
|
|
401
|
+
<a name='L336'></a><a href='#L336'>336</a>
|
|
402
|
+
<a name='L337'></a><a href='#L337'>337</a>
|
|
403
|
+
<a name='L338'></a><a href='#L338'>338</a>
|
|
404
|
+
<a name='L339'></a><a href='#L339'>339</a>
|
|
405
|
+
<a name='L340'></a><a href='#L340'>340</a>
|
|
406
|
+
<a name='L341'></a><a href='#L341'>341</a>
|
|
407
|
+
<a name='L342'></a><a href='#L342'>342</a>
|
|
408
|
+
<a name='L343'></a><a href='#L343'>343</a>
|
|
409
|
+
<a name='L344'></a><a href='#L344'>344</a>
|
|
410
|
+
<a name='L345'></a><a href='#L345'>345</a>
|
|
411
|
+
<a name='L346'></a><a href='#L346'>346</a>
|
|
412
|
+
<a name='L347'></a><a href='#L347'>347</a>
|
|
413
|
+
<a name='L348'></a><a href='#L348'>348</a>
|
|
414
|
+
<a name='L349'></a><a href='#L349'>349</a>
|
|
415
|
+
<a name='L350'></a><a href='#L350'>350</a>
|
|
416
|
+
<a name='L351'></a><a href='#L351'>351</a>
|
|
417
|
+
<a name='L352'></a><a href='#L352'>352</a>
|
|
418
|
+
<a name='L353'></a><a href='#L353'>353</a>
|
|
419
|
+
<a name='L354'></a><a href='#L354'>354</a>
|
|
420
|
+
<a name='L355'></a><a href='#L355'>355</a>
|
|
421
|
+
<a name='L356'></a><a href='#L356'>356</a>
|
|
422
|
+
<a name='L357'></a><a href='#L357'>357</a>
|
|
423
|
+
<a name='L358'></a><a href='#L358'>358</a>
|
|
424
|
+
<a name='L359'></a><a href='#L359'>359</a>
|
|
425
|
+
<a name='L360'></a><a href='#L360'>360</a>
|
|
426
|
+
<a name='L361'></a><a href='#L361'>361</a>
|
|
427
|
+
<a name='L362'></a><a href='#L362'>362</a>
|
|
428
|
+
<a name='L363'></a><a href='#L363'>363</a>
|
|
429
|
+
<a name='L364'></a><a href='#L364'>364</a>
|
|
430
|
+
<a name='L365'></a><a href='#L365'>365</a>
|
|
431
|
+
<a name='L366'></a><a href='#L366'>366</a>
|
|
432
|
+
<a name='L367'></a><a href='#L367'>367</a>
|
|
433
|
+
<a name='L368'></a><a href='#L368'>368</a>
|
|
434
|
+
<a name='L369'></a><a href='#L369'>369</a>
|
|
435
|
+
<a name='L370'></a><a href='#L370'>370</a>
|
|
436
|
+
<a name='L371'></a><a href='#L371'>371</a>
|
|
437
|
+
<a name='L372'></a><a href='#L372'>372</a>
|
|
438
|
+
<a name='L373'></a><a href='#L373'>373</a>
|
|
439
|
+
<a name='L374'></a><a href='#L374'>374</a>
|
|
440
|
+
<a name='L375'></a><a href='#L375'>375</a>
|
|
441
|
+
<a name='L376'></a><a href='#L376'>376</a>
|
|
442
|
+
<a name='L377'></a><a href='#L377'>377</a>
|
|
443
|
+
<a name='L378'></a><a href='#L378'>378</a>
|
|
444
|
+
<a name='L379'></a><a href='#L379'>379</a>
|
|
445
|
+
<a name='L380'></a><a href='#L380'>380</a>
|
|
446
|
+
<a name='L381'></a><a href='#L381'>381</a>
|
|
447
|
+
<a name='L382'></a><a href='#L382'>382</a>
|
|
448
|
+
<a name='L383'></a><a href='#L383'>383</a>
|
|
449
|
+
<a name='L384'></a><a href='#L384'>384</a>
|
|
450
|
+
<a name='L385'></a><a href='#L385'>385</a>
|
|
451
|
+
<a name='L386'></a><a href='#L386'>386</a>
|
|
452
|
+
<a name='L387'></a><a href='#L387'>387</a>
|
|
453
|
+
<a name='L388'></a><a href='#L388'>388</a>
|
|
454
|
+
<a name='L389'></a><a href='#L389'>389</a>
|
|
455
|
+
<a name='L390'></a><a href='#L390'>390</a>
|
|
456
|
+
<a name='L391'></a><a href='#L391'>391</a>
|
|
457
|
+
<a name='L392'></a><a href='#L392'>392</a>
|
|
458
|
+
<a name='L393'></a><a href='#L393'>393</a>
|
|
459
|
+
<a name='L394'></a><a href='#L394'>394</a>
|
|
460
|
+
<a name='L395'></a><a href='#L395'>395</a>
|
|
461
|
+
<a name='L396'></a><a href='#L396'>396</a>
|
|
462
|
+
<a name='L397'></a><a href='#L397'>397</a>
|
|
463
|
+
<a name='L398'></a><a href='#L398'>398</a>
|
|
464
|
+
<a name='L399'></a><a href='#L399'>399</a>
|
|
465
|
+
<a name='L400'></a><a href='#L400'>400</a>
|
|
466
|
+
<a name='L401'></a><a href='#L401'>401</a>
|
|
467
|
+
<a name='L402'></a><a href='#L402'>402</a>
|
|
468
|
+
<a name='L403'></a><a href='#L403'>403</a>
|
|
469
|
+
<a name='L404'></a><a href='#L404'>404</a>
|
|
470
|
+
<a name='L405'></a><a href='#L405'>405</a>
|
|
471
|
+
<a name='L406'></a><a href='#L406'>406</a>
|
|
472
|
+
<a name='L407'></a><a href='#L407'>407</a>
|
|
473
|
+
<a name='L408'></a><a href='#L408'>408</a>
|
|
474
|
+
<a name='L409'></a><a href='#L409'>409</a>
|
|
475
|
+
<a name='L410'></a><a href='#L410'>410</a>
|
|
476
|
+
<a name='L411'></a><a href='#L411'>411</a>
|
|
477
|
+
<a name='L412'></a><a href='#L412'>412</a>
|
|
478
|
+
<a name='L413'></a><a href='#L413'>413</a>
|
|
479
|
+
<a name='L414'></a><a href='#L414'>414</a>
|
|
480
|
+
<a name='L415'></a><a href='#L415'>415</a>
|
|
481
|
+
<a name='L416'></a><a href='#L416'>416</a>
|
|
482
|
+
<a name='L417'></a><a href='#L417'>417</a>
|
|
483
|
+
<a name='L418'></a><a href='#L418'>418</a>
|
|
484
|
+
<a name='L419'></a><a href='#L419'>419</a>
|
|
485
|
+
<a name='L420'></a><a href='#L420'>420</a>
|
|
486
|
+
<a name='L421'></a><a href='#L421'>421</a>
|
|
487
|
+
<a name='L422'></a><a href='#L422'>422</a>
|
|
488
|
+
<a name='L423'></a><a href='#L423'>423</a>
|
|
489
|
+
<a name='L424'></a><a href='#L424'>424</a>
|
|
490
|
+
<a name='L425'></a><a href='#L425'>425</a>
|
|
491
|
+
<a name='L426'></a><a href='#L426'>426</a>
|
|
492
|
+
<a name='L427'></a><a href='#L427'>427</a>
|
|
493
|
+
<a name='L428'></a><a href='#L428'>428</a>
|
|
494
|
+
<a name='L429'></a><a href='#L429'>429</a>
|
|
495
|
+
<a name='L430'></a><a href='#L430'>430</a>
|
|
496
|
+
<a name='L431'></a><a href='#L431'>431</a>
|
|
497
|
+
<a name='L432'></a><a href='#L432'>432</a>
|
|
498
|
+
<a name='L433'></a><a href='#L433'>433</a>
|
|
499
|
+
<a name='L434'></a><a href='#L434'>434</a>
|
|
500
|
+
<a name='L435'></a><a href='#L435'>435</a>
|
|
501
|
+
<a name='L436'></a><a href='#L436'>436</a>
|
|
502
|
+
<a name='L437'></a><a href='#L437'>437</a>
|
|
503
|
+
<a name='L438'></a><a href='#L438'>438</a>
|
|
504
|
+
<a name='L439'></a><a href='#L439'>439</a>
|
|
505
|
+
<a name='L440'></a><a href='#L440'>440</a>
|
|
506
|
+
<a name='L441'></a><a href='#L441'>441</a>
|
|
507
|
+
<a name='L442'></a><a href='#L442'>442</a>
|
|
508
|
+
<a name='L443'></a><a href='#L443'>443</a>
|
|
509
|
+
<a name='L444'></a><a href='#L444'>444</a>
|
|
510
|
+
<a name='L445'></a><a href='#L445'>445</a>
|
|
511
|
+
<a name='L446'></a><a href='#L446'>446</a>
|
|
512
|
+
<a name='L447'></a><a href='#L447'>447</a>
|
|
513
|
+
<a name='L448'></a><a href='#L448'>448</a>
|
|
514
|
+
<a name='L449'></a><a href='#L449'>449</a>
|
|
515
|
+
<a name='L450'></a><a href='#L450'>450</a>
|
|
516
|
+
<a name='L451'></a><a href='#L451'>451</a>
|
|
517
|
+
<a name='L452'></a><a href='#L452'>452</a>
|
|
518
|
+
<a name='L453'></a><a href='#L453'>453</a>
|
|
519
|
+
<a name='L454'></a><a href='#L454'>454</a>
|
|
520
|
+
<a name='L455'></a><a href='#L455'>455</a>
|
|
521
|
+
<a name='L456'></a><a href='#L456'>456</a></td><td class="line-coverage quiet"><span class="cline-any cline-yes">1x</span>
|
|
522
|
+
<span class="cline-any cline-yes">1x</span>
|
|
523
|
+
<span class="cline-any cline-yes">1x</span>
|
|
524
|
+
<span class="cline-any cline-yes">1x</span>
|
|
525
|
+
<span class="cline-any cline-yes">1x</span>
|
|
526
|
+
<span class="cline-any cline-yes">1x</span>
|
|
527
|
+
<span class="cline-any cline-yes">1x</span>
|
|
528
|
+
<span class="cline-any cline-yes">1x</span>
|
|
529
|
+
<span class="cline-any cline-yes">1x</span>
|
|
530
|
+
<span class="cline-any cline-yes">1x</span>
|
|
531
|
+
<span class="cline-any cline-yes">1x</span>
|
|
532
|
+
<span class="cline-any cline-yes">1x</span>
|
|
533
|
+
<span class="cline-any cline-yes">1x</span>
|
|
534
|
+
<span class="cline-any cline-yes">1x</span>
|
|
535
|
+
<span class="cline-any cline-yes">1x</span>
|
|
536
|
+
<span class="cline-any cline-yes">1x</span>
|
|
537
|
+
<span class="cline-any cline-yes">1x</span>
|
|
538
|
+
<span class="cline-any cline-yes">1x</span>
|
|
539
|
+
<span class="cline-any cline-yes">1x</span>
|
|
540
|
+
<span class="cline-any cline-yes">1x</span>
|
|
541
|
+
<span class="cline-any cline-yes">1x</span>
|
|
542
|
+
<span class="cline-any cline-yes">1x</span>
|
|
543
|
+
<span class="cline-any cline-yes">1x</span>
|
|
544
|
+
<span class="cline-any cline-yes">1x</span>
|
|
545
|
+
<span class="cline-any cline-yes">1x</span>
|
|
546
|
+
<span class="cline-any cline-yes">1x</span>
|
|
547
|
+
<span class="cline-any cline-yes">1x</span>
|
|
548
|
+
<span class="cline-any cline-yes">1x</span>
|
|
549
|
+
<span class="cline-any cline-yes">1x</span>
|
|
550
|
+
<span class="cline-any cline-yes">1x</span>
|
|
551
|
+
<span class="cline-any cline-yes">1x</span>
|
|
552
|
+
<span class="cline-any cline-yes">1x</span>
|
|
553
|
+
<span class="cline-any cline-yes">1x</span>
|
|
554
|
+
<span class="cline-any cline-yes">1x</span>
|
|
555
|
+
<span class="cline-any cline-yes">1x</span>
|
|
556
|
+
<span class="cline-any cline-yes">1x</span>
|
|
557
|
+
<span class="cline-any cline-yes">1x</span>
|
|
558
|
+
<span class="cline-any cline-yes">1x</span>
|
|
559
|
+
<span class="cline-any cline-yes">1x</span>
|
|
560
|
+
<span class="cline-any cline-yes">1x</span>
|
|
561
|
+
<span class="cline-any cline-yes">1x</span>
|
|
562
|
+
<span class="cline-any cline-yes">1x</span>
|
|
563
|
+
<span class="cline-any cline-yes">1x</span>
|
|
564
|
+
<span class="cline-any cline-yes">1x</span>
|
|
565
|
+
<span class="cline-any cline-yes">1x</span>
|
|
566
|
+
<span class="cline-any cline-yes">1x</span>
|
|
567
|
+
<span class="cline-any cline-yes">1x</span>
|
|
568
|
+
<span class="cline-any cline-yes">1x</span>
|
|
569
|
+
<span class="cline-any cline-yes">1x</span>
|
|
570
|
+
<span class="cline-any cline-yes">1x</span>
|
|
571
|
+
<span class="cline-any cline-yes">1x</span>
|
|
572
|
+
<span class="cline-any cline-yes">1x</span>
|
|
573
|
+
<span class="cline-any cline-yes">46x</span>
|
|
574
|
+
<span class="cline-any cline-yes">46x</span>
|
|
575
|
+
<span class="cline-any cline-yes">46x</span>
|
|
576
|
+
<span class="cline-any cline-yes">46x</span>
|
|
577
|
+
<span class="cline-any cline-yes">46x</span>
|
|
578
|
+
<span class="cline-any cline-yes">46x</span>
|
|
579
|
+
<span class="cline-any cline-yes">46x</span>
|
|
580
|
+
<span class="cline-any cline-yes">46x</span>
|
|
581
|
+
<span class="cline-any cline-yes">46x</span>
|
|
582
|
+
<span class="cline-any cline-yes">46x</span>
|
|
583
|
+
<span class="cline-any cline-yes">46x</span>
|
|
584
|
+
<span class="cline-any cline-yes">1x</span>
|
|
585
|
+
<span class="cline-any cline-yes">1x</span>
|
|
586
|
+
<span class="cline-any cline-yes">1x</span>
|
|
587
|
+
<span class="cline-any cline-yes">1x</span>
|
|
588
|
+
<span class="cline-any cline-yes">1x</span>
|
|
589
|
+
<span class="cline-any cline-yes">47x</span>
|
|
590
|
+
<span class="cline-any cline-yes">47x</span>
|
|
591
|
+
<span class="cline-any cline-yes">47x</span>
|
|
592
|
+
<span class="cline-any cline-yes">47x</span>
|
|
593
|
+
<span class="cline-any cline-yes">47x</span>
|
|
594
|
+
<span class="cline-any cline-yes">47x</span>
|
|
595
|
+
<span class="cline-any cline-yes">47x</span>
|
|
596
|
+
<span class="cline-any cline-yes">47x</span>
|
|
597
|
+
<span class="cline-any cline-yes">46x</span>
|
|
598
|
+
<span class="cline-any cline-yes">2x</span>
|
|
599
|
+
<span class="cline-any cline-yes">2x</span>
|
|
600
|
+
<span class="cline-any cline-yes">44x</span>
|
|
601
|
+
<span class="cline-any cline-yes">44x</span>
|
|
602
|
+
<span class="cline-any cline-yes">46x</span>
|
|
603
|
+
<span class="cline-any cline-yes">46x</span>
|
|
604
|
+
<span class="cline-any cline-yes">46x</span>
|
|
605
|
+
<span class="cline-any cline-yes">34x</span>
|
|
606
|
+
<span class="cline-any cline-no"> </span>
|
|
607
|
+
<span class="cline-any cline-no"> </span>
|
|
608
|
+
<span class="cline-any cline-yes">34x</span>
|
|
609
|
+
<span class="cline-any cline-yes">34x</span>
|
|
610
|
+
<span class="cline-any cline-yes">10x</span>
|
|
611
|
+
<span class="cline-any cline-yes">24x</span>
|
|
612
|
+
<span class="cline-any cline-yes">2x</span>
|
|
613
|
+
<span class="cline-any cline-yes">2x</span>
|
|
614
|
+
<span class="cline-any cline-yes">2x</span>
|
|
615
|
+
<span class="cline-any cline-yes">2x</span>
|
|
616
|
+
<span class="cline-any cline-yes">2x</span>
|
|
617
|
+
<span class="cline-any cline-yes">10x</span>
|
|
618
|
+
<span class="cline-any cline-yes">10x</span>
|
|
619
|
+
<span class="cline-any cline-yes">10x</span>
|
|
620
|
+
<span class="cline-any cline-yes">10x</span>
|
|
621
|
+
<span class="cline-any cline-yes">10x</span>
|
|
622
|
+
<span class="cline-any cline-yes">10x</span>
|
|
623
|
+
<span class="cline-any cline-yes">10x</span>
|
|
624
|
+
<span class="cline-any cline-yes">2x</span>
|
|
625
|
+
<span class="cline-any cline-yes">2x</span>
|
|
626
|
+
<span class="cline-any cline-yes">10x</span>
|
|
627
|
+
<span class="cline-any cline-yes">10x</span>
|
|
628
|
+
<span class="cline-any cline-yes">10x</span>
|
|
629
|
+
<span class="cline-any cline-yes">10x</span>
|
|
630
|
+
<span class="cline-any cline-yes">46x</span>
|
|
631
|
+
<span class="cline-any cline-yes">2x</span>
|
|
632
|
+
<span class="cline-any cline-yes">2x</span>
|
|
633
|
+
<span class="cline-any cline-yes">2x</span>
|
|
634
|
+
<span class="cline-any cline-no"> </span>
|
|
635
|
+
<span class="cline-any cline-no"> </span>
|
|
636
|
+
<span class="cline-any cline-yes">2x</span>
|
|
637
|
+
<span class="cline-any cline-yes">47x</span>
|
|
638
|
+
<span class="cline-any cline-yes">47x</span>
|
|
639
|
+
<span class="cline-any cline-yes">1x</span>
|
|
640
|
+
<span class="cline-any cline-yes">1x</span>
|
|
641
|
+
<span class="cline-any cline-yes">1x</span>
|
|
642
|
+
<span class="cline-any cline-yes">1x</span>
|
|
643
|
+
<span class="cline-any cline-yes">1x</span>
|
|
644
|
+
<span class="cline-any cline-yes">1x</span>
|
|
645
|
+
<span class="cline-any cline-yes">1x</span>
|
|
646
|
+
<span class="cline-any cline-yes">1x</span>
|
|
647
|
+
<span class="cline-any cline-yes">1x</span>
|
|
648
|
+
<span class="cline-any cline-yes">1x</span>
|
|
649
|
+
<span class="cline-any cline-yes">1x</span>
|
|
650
|
+
<span class="cline-any cline-yes">1x</span>
|
|
651
|
+
<span class="cline-any cline-yes">1x</span>
|
|
652
|
+
<span class="cline-any cline-yes">1x</span>
|
|
653
|
+
<span class="cline-any cline-yes">1x</span>
|
|
654
|
+
<span class="cline-any cline-yes">1x</span>
|
|
655
|
+
<span class="cline-any cline-yes">1x</span>
|
|
656
|
+
<span class="cline-any cline-yes">1x</span>
|
|
657
|
+
<span class="cline-any cline-yes">1x</span>
|
|
658
|
+
<span class="cline-any cline-yes">1x</span>
|
|
659
|
+
<span class="cline-any cline-yes">1x</span>
|
|
660
|
+
<span class="cline-any cline-yes">1x</span>
|
|
661
|
+
<span class="cline-any cline-yes">1x</span>
|
|
662
|
+
<span class="cline-any cline-yes">1x</span>
|
|
663
|
+
<span class="cline-any cline-yes">1x</span>
|
|
664
|
+
<span class="cline-any cline-yes">1x</span>
|
|
665
|
+
<span class="cline-any cline-yes">1x</span>
|
|
666
|
+
<span class="cline-any cline-yes">1x</span>
|
|
667
|
+
<span class="cline-any cline-yes">1x</span>
|
|
668
|
+
<span class="cline-any cline-yes">1x</span>
|
|
669
|
+
<span class="cline-any cline-yes">1x</span>
|
|
670
|
+
<span class="cline-any cline-yes">1x</span>
|
|
671
|
+
<span class="cline-any cline-yes">1x</span>
|
|
672
|
+
<span class="cline-any cline-yes">1x</span>
|
|
673
|
+
<span class="cline-any cline-yes">1x</span>
|
|
674
|
+
<span class="cline-any cline-yes">1x</span>
|
|
675
|
+
<span class="cline-any cline-yes">1x</span>
|
|
676
|
+
<span class="cline-any cline-yes">1x</span>
|
|
677
|
+
<span class="cline-any cline-yes">1x</span>
|
|
678
|
+
<span class="cline-any cline-yes">1x</span>
|
|
679
|
+
<span class="cline-any cline-yes">1x</span>
|
|
680
|
+
<span class="cline-any cline-yes">1x</span>
|
|
681
|
+
<span class="cline-any cline-yes">1x</span>
|
|
682
|
+
<span class="cline-any cline-yes">1x</span>
|
|
683
|
+
<span class="cline-any cline-yes">1x</span>
|
|
684
|
+
<span class="cline-any cline-yes">1x</span>
|
|
685
|
+
<span class="cline-any cline-yes">1x</span>
|
|
686
|
+
<span class="cline-any cline-yes">1x</span>
|
|
687
|
+
<span class="cline-any cline-yes">1x</span>
|
|
688
|
+
<span class="cline-any cline-yes">1x</span>
|
|
689
|
+
<span class="cline-any cline-yes">1x</span>
|
|
690
|
+
<span class="cline-any cline-yes">47x</span>
|
|
691
|
+
<span class="cline-any cline-yes">47x</span>
|
|
692
|
+
<span class="cline-any cline-yes">47x</span>
|
|
693
|
+
<span class="cline-any cline-yes">47x</span>
|
|
694
|
+
<span class="cline-any cline-yes">47x</span>
|
|
695
|
+
<span class="cline-any cline-yes">47x</span>
|
|
696
|
+
<span class="cline-any cline-yes">47x</span>
|
|
697
|
+
<span class="cline-any cline-yes">47x</span>
|
|
698
|
+
<span class="cline-any cline-yes">47x</span>
|
|
699
|
+
<span class="cline-any cline-yes">47x</span>
|
|
700
|
+
<span class="cline-any cline-yes">47x</span>
|
|
701
|
+
<span class="cline-any cline-yes">47x</span>
|
|
702
|
+
<span class="cline-any cline-yes">47x</span>
|
|
703
|
+
<span class="cline-any cline-yes">47x</span>
|
|
704
|
+
<span class="cline-any cline-yes">47x</span>
|
|
705
|
+
<span class="cline-any cline-yes">47x</span>
|
|
706
|
+
<span class="cline-any cline-yes">47x</span>
|
|
707
|
+
<span class="cline-any cline-yes">22x</span>
|
|
708
|
+
<span class="cline-any cline-yes">22x</span>
|
|
709
|
+
<span class="cline-any cline-yes">22x</span>
|
|
710
|
+
<span class="cline-any cline-yes">22x</span>
|
|
711
|
+
<span class="cline-any cline-yes">22x</span>
|
|
712
|
+
<span class="cline-any cline-yes">22x</span>
|
|
713
|
+
<span class="cline-any cline-yes">47x</span>
|
|
714
|
+
<span class="cline-any cline-yes">47x</span>
|
|
715
|
+
<span class="cline-any cline-yes">47x</span>
|
|
716
|
+
<span class="cline-any cline-yes">47x</span>
|
|
717
|
+
<span class="cline-any cline-yes">47x</span>
|
|
718
|
+
<span class="cline-any cline-yes">47x</span>
|
|
719
|
+
<span class="cline-any cline-yes">47x</span>
|
|
720
|
+
<span class="cline-any cline-yes">47x</span>
|
|
721
|
+
<span class="cline-any cline-yes">47x</span>
|
|
722
|
+
<span class="cline-any cline-yes">47x</span>
|
|
723
|
+
<span class="cline-any cline-yes">47x</span>
|
|
724
|
+
<span class="cline-any cline-yes">47x</span>
|
|
725
|
+
<span class="cline-any cline-yes">47x</span>
|
|
726
|
+
<span class="cline-any cline-yes">47x</span>
|
|
727
|
+
<span class="cline-any cline-yes">47x</span>
|
|
728
|
+
<span class="cline-any cline-yes">26x</span>
|
|
729
|
+
<span class="cline-any cline-yes">26x</span>
|
|
730
|
+
<span class="cline-any cline-no"> </span>
|
|
731
|
+
<span class="cline-any cline-no"> </span>
|
|
732
|
+
<span class="cline-any cline-no"> </span>
|
|
733
|
+
<span class="cline-any cline-no"> </span>
|
|
734
|
+
<span class="cline-any cline-no"> </span>
|
|
735
|
+
<span class="cline-any cline-yes">26x</span>
|
|
736
|
+
<span class="cline-any cline-yes">26x</span>
|
|
737
|
+
<span class="cline-any cline-yes">26x</span>
|
|
738
|
+
<span class="cline-any cline-yes">3x</span>
|
|
739
|
+
<span class="cline-any cline-yes">3x</span>
|
|
740
|
+
<span class="cline-any cline-yes">3x</span>
|
|
741
|
+
<span class="cline-any cline-yes">23x</span>
|
|
742
|
+
<span class="cline-any cline-yes">23x</span>
|
|
743
|
+
<span class="cline-any cline-yes">23x</span>
|
|
744
|
+
<span class="cline-any cline-yes">23x</span>
|
|
745
|
+
<span class="cline-any cline-yes">26x</span>
|
|
746
|
+
<span class="cline-any cline-no"> </span>
|
|
747
|
+
<span class="cline-any cline-no"> </span>
|
|
748
|
+
<span class="cline-any cline-no"> </span>
|
|
749
|
+
<span class="cline-any cline-yes">23x</span>
|
|
750
|
+
<span class="cline-any cline-yes">23x</span>
|
|
751
|
+
<span class="cline-any cline-yes">26x</span>
|
|
752
|
+
<span class="cline-any cline-no"> </span>
|
|
753
|
+
<span class="cline-any cline-no"> </span>
|
|
754
|
+
<span class="cline-any cline-no"> </span>
|
|
755
|
+
<span class="cline-any cline-no"> </span>
|
|
756
|
+
<span class="cline-any cline-no"> </span>
|
|
757
|
+
<span class="cline-any cline-no"> </span>
|
|
758
|
+
<span class="cline-any cline-no"> </span>
|
|
759
|
+
<span class="cline-any cline-no"> </span>
|
|
760
|
+
<span class="cline-any cline-no"> </span>
|
|
761
|
+
<span class="cline-any cline-no"> </span>
|
|
762
|
+
<span class="cline-any cline-no"> </span>
|
|
763
|
+
<span class="cline-any cline-yes">23x</span>
|
|
764
|
+
<span class="cline-any cline-yes">23x</span>
|
|
765
|
+
<span class="cline-any cline-yes">23x</span>
|
|
766
|
+
<span class="cline-any cline-yes">23x</span>
|
|
767
|
+
<span class="cline-any cline-yes">23x</span>
|
|
768
|
+
<span class="cline-any cline-yes">23x</span>
|
|
769
|
+
<span class="cline-any cline-yes">23x</span>
|
|
770
|
+
<span class="cline-any cline-yes">23x</span>
|
|
771
|
+
<span class="cline-any cline-yes">23x</span>
|
|
772
|
+
<span class="cline-any cline-yes">23x</span>
|
|
773
|
+
<span class="cline-any cline-yes">26x</span>
|
|
774
|
+
<span class="cline-any cline-no"> </span>
|
|
775
|
+
<span class="cline-any cline-no"> </span>
|
|
776
|
+
<span class="cline-any cline-no"> </span>
|
|
777
|
+
<span class="cline-any cline-no"> </span>
|
|
778
|
+
<span class="cline-any cline-no"> </span>
|
|
779
|
+
<span class="cline-any cline-no"> </span>
|
|
780
|
+
<span class="cline-any cline-no"> </span>
|
|
781
|
+
<span class="cline-any cline-no"> </span>
|
|
782
|
+
<span class="cline-any cline-no"> </span>
|
|
783
|
+
<span class="cline-any cline-no"> </span>
|
|
784
|
+
<span class="cline-any cline-no"> </span>
|
|
785
|
+
<span class="cline-any cline-no"> </span>
|
|
786
|
+
<span class="cline-any cline-no"> </span>
|
|
787
|
+
<span class="cline-any cline-no"> </span>
|
|
788
|
+
<span class="cline-any cline-no"> </span>
|
|
789
|
+
<span class="cline-any cline-no"> </span>
|
|
790
|
+
<span class="cline-any cline-no"> </span>
|
|
791
|
+
<span class="cline-any cline-no"> </span>
|
|
792
|
+
<span class="cline-any cline-no"> </span>
|
|
793
|
+
<span class="cline-any cline-no"> </span>
|
|
794
|
+
<span class="cline-any cline-no"> </span>
|
|
795
|
+
<span class="cline-any cline-no"> </span>
|
|
796
|
+
<span class="cline-any cline-no"> </span>
|
|
797
|
+
<span class="cline-any cline-no"> </span>
|
|
798
|
+
<span class="cline-any cline-yes">23x</span>
|
|
799
|
+
<span class="cline-any cline-yes">23x</span>
|
|
800
|
+
<span class="cline-any cline-yes">23x</span>
|
|
801
|
+
<span class="cline-any cline-yes">23x</span>
|
|
802
|
+
<span class="cline-any cline-yes">23x</span>
|
|
803
|
+
<span class="cline-any cline-yes">23x</span>
|
|
804
|
+
<span class="cline-any cline-yes">23x</span>
|
|
805
|
+
<span class="cline-any cline-yes">23x</span>
|
|
806
|
+
<span class="cline-any cline-yes">23x</span>
|
|
807
|
+
<span class="cline-any cline-yes">23x</span>
|
|
808
|
+
<span class="cline-any cline-yes">23x</span>
|
|
809
|
+
<span class="cline-any cline-yes">23x</span>
|
|
810
|
+
<span class="cline-any cline-yes">23x</span>
|
|
811
|
+
<span class="cline-any cline-yes">23x</span>
|
|
812
|
+
<span class="cline-any cline-yes">20x</span>
|
|
813
|
+
<span class="cline-any cline-yes">20x</span>
|
|
814
|
+
<span class="cline-any cline-yes">20x</span>
|
|
815
|
+
<span class="cline-any cline-yes">20x</span>
|
|
816
|
+
<span class="cline-any cline-yes">20x</span>
|
|
817
|
+
<span class="cline-any cline-yes">40x</span>
|
|
818
|
+
<span class="cline-any cline-yes">40x</span>
|
|
819
|
+
<span class="cline-any cline-yes">40x</span>
|
|
820
|
+
<span class="cline-any cline-yes">40x</span>
|
|
821
|
+
<span class="cline-any cline-yes">40x</span>
|
|
822
|
+
<span class="cline-any cline-yes">20x</span>
|
|
823
|
+
<span class="cline-any cline-yes">20x</span>
|
|
824
|
+
<span class="cline-any cline-yes">23x</span>
|
|
825
|
+
<span class="cline-any cline-yes">1x</span>
|
|
826
|
+
<span class="cline-any cline-yes">1x</span>
|
|
827
|
+
<span class="cline-any cline-yes">1x</span>
|
|
828
|
+
<span class="cline-any cline-yes">1x</span>
|
|
829
|
+
<span class="cline-any cline-yes">1x</span>
|
|
830
|
+
<span class="cline-any cline-yes">20x</span>
|
|
831
|
+
<span class="cline-any cline-yes">20x</span>
|
|
832
|
+
<span class="cline-any cline-yes">23x</span>
|
|
833
|
+
<span class="cline-any cline-yes">3x</span>
|
|
834
|
+
<span class="cline-any cline-yes">3x</span>
|
|
835
|
+
<span class="cline-any cline-yes">3x</span>
|
|
836
|
+
<span class="cline-any cline-yes">3x</span>
|
|
837
|
+
<span class="cline-any cline-yes">3x</span>
|
|
838
|
+
<span class="cline-any cline-yes">3x</span>
|
|
839
|
+
<span class="cline-any cline-yes">3x</span>
|
|
840
|
+
<span class="cline-any cline-yes">6x</span>
|
|
841
|
+
<span class="cline-any cline-yes">6x</span>
|
|
842
|
+
<span class="cline-any cline-yes">6x</span>
|
|
843
|
+
<span class="cline-any cline-yes">6x</span>
|
|
844
|
+
<span class="cline-any cline-yes">6x</span>
|
|
845
|
+
<span class="cline-any cline-yes">6x</span>
|
|
846
|
+
<span class="cline-any cline-yes">6x</span>
|
|
847
|
+
<span class="cline-any cline-yes">3x</span>
|
|
848
|
+
<span class="cline-any cline-yes">3x</span>
|
|
849
|
+
<span class="cline-any cline-yes">3x</span>
|
|
850
|
+
<span class="cline-any cline-no"> </span>
|
|
851
|
+
<span class="cline-any cline-no"> </span>
|
|
852
|
+
<span class="cline-any cline-yes">3x</span>
|
|
853
|
+
<span class="cline-any cline-yes">3x</span>
|
|
854
|
+
<span class="cline-any cline-yes">3x</span>
|
|
855
|
+
<span class="cline-any cline-yes">23x</span>
|
|
856
|
+
<span class="cline-any cline-yes">23x</span>
|
|
857
|
+
<span class="cline-any cline-yes">23x</span>
|
|
858
|
+
<span class="cline-any cline-yes">23x</span>
|
|
859
|
+
<span class="cline-any cline-yes">23x</span>
|
|
860
|
+
<span class="cline-any cline-yes">23x</span>
|
|
861
|
+
<span class="cline-any cline-yes">23x</span>
|
|
862
|
+
<span class="cline-any cline-yes">23x</span>
|
|
863
|
+
<span class="cline-any cline-yes">23x</span>
|
|
864
|
+
<span class="cline-any cline-yes">23x</span>
|
|
865
|
+
<span class="cline-any cline-yes">23x</span>
|
|
866
|
+
<span class="cline-any cline-yes">23x</span>
|
|
867
|
+
<span class="cline-any cline-yes">23x</span>
|
|
868
|
+
<span class="cline-any cline-yes">23x</span>
|
|
869
|
+
<span class="cline-any cline-yes">23x</span>
|
|
870
|
+
<span class="cline-any cline-yes">23x</span>
|
|
871
|
+
<span class="cline-any cline-yes">23x</span>
|
|
872
|
+
<span class="cline-any cline-yes">23x</span>
|
|
873
|
+
<span class="cline-any cline-yes">26x</span>
|
|
874
|
+
<span class="cline-any cline-yes">47x</span>
|
|
875
|
+
<span class="cline-any cline-yes">47x</span>
|
|
876
|
+
<span class="cline-any cline-yes">47x</span>
|
|
877
|
+
<span class="cline-any cline-yes">26x</span>
|
|
878
|
+
<span class="cline-any cline-yes">26x</span>
|
|
879
|
+
<span class="cline-any cline-yes">26x</span>
|
|
880
|
+
<span class="cline-any cline-yes">26x</span>
|
|
881
|
+
<span class="cline-any cline-yes">26x</span>
|
|
882
|
+
<span class="cline-any cline-yes">26x</span>
|
|
883
|
+
<span class="cline-any cline-yes">47x</span>
|
|
884
|
+
<span class="cline-any cline-yes">47x</span>
|
|
885
|
+
<span class="cline-any cline-yes">47x</span>
|
|
886
|
+
<span class="cline-any cline-yes">47x</span>
|
|
887
|
+
<span class="cline-any cline-yes">46x</span>
|
|
888
|
+
<span class="cline-any cline-yes">11x</span>
|
|
889
|
+
<span class="cline-any cline-yes">11x</span>
|
|
890
|
+
<span class="cline-any cline-yes">11x</span>
|
|
891
|
+
<span class="cline-any cline-yes">11x</span>
|
|
892
|
+
<span class="cline-any cline-yes">11x</span>
|
|
893
|
+
<span class="cline-any cline-no"> </span>
|
|
894
|
+
<span class="cline-any cline-no"> </span>
|
|
895
|
+
<span class="cline-any cline-no"> </span>
|
|
896
|
+
<span class="cline-any cline-no"> </span>
|
|
897
|
+
<span class="cline-any cline-no"> </span>
|
|
898
|
+
<span class="cline-any cline-no"> </span>
|
|
899
|
+
<span class="cline-any cline-no"> </span>
|
|
900
|
+
<span class="cline-any cline-no"> </span>
|
|
901
|
+
<span class="cline-any cline-yes">11x</span>
|
|
902
|
+
<span class="cline-any cline-yes">11x</span>
|
|
903
|
+
<span class="cline-any cline-yes">11x</span>
|
|
904
|
+
<span class="cline-any cline-no"> </span>
|
|
905
|
+
<span class="cline-any cline-no"> </span>
|
|
906
|
+
<span class="cline-any cline-no"> </span>
|
|
907
|
+
<span class="cline-any cline-yes">11x</span>
|
|
908
|
+
<span class="cline-any cline-yes">11x</span>
|
|
909
|
+
<span class="cline-any cline-yes">11x</span>
|
|
910
|
+
<span class="cline-any cline-yes">1x</span>
|
|
911
|
+
<span class="cline-any cline-yes">1x</span>
|
|
912
|
+
<span class="cline-any cline-yes">1x</span>
|
|
913
|
+
<span class="cline-any cline-yes">1x</span>
|
|
914
|
+
<span class="cline-any cline-yes">1x</span>
|
|
915
|
+
<span class="cline-any cline-yes">11x</span>
|
|
916
|
+
<span class="cline-any cline-yes">11x</span>
|
|
917
|
+
<span class="cline-any cline-yes">11x</span>
|
|
918
|
+
<span class="cline-any cline-yes">47x</span>
|
|
919
|
+
<span class="cline-any cline-yes">47x</span>
|
|
920
|
+
<span class="cline-any cline-yes">47x</span>
|
|
921
|
+
<span class="cline-any cline-yes">47x</span>
|
|
922
|
+
<span class="cline-any cline-yes">47x</span>
|
|
923
|
+
<span class="cline-any cline-yes">47x</span>
|
|
924
|
+
<span class="cline-any cline-yes">47x</span>
|
|
925
|
+
<span class="cline-any cline-yes">47x</span>
|
|
926
|
+
<span class="cline-any cline-yes">47x</span>
|
|
927
|
+
<span class="cline-any cline-yes">47x</span>
|
|
928
|
+
<span class="cline-any cline-yes">47x</span>
|
|
929
|
+
<span class="cline-any cline-yes">47x</span>
|
|
930
|
+
<span class="cline-any cline-yes">47x</span>
|
|
931
|
+
<span class="cline-any cline-yes">47x</span>
|
|
932
|
+
<span class="cline-any cline-yes">47x</span>
|
|
933
|
+
<span class="cline-any cline-yes">47x</span>
|
|
934
|
+
<span class="cline-any cline-yes">47x</span>
|
|
935
|
+
<span class="cline-any cline-no"> </span>
|
|
936
|
+
<span class="cline-any cline-no"> </span>
|
|
937
|
+
<span class="cline-any cline-no"> </span>
|
|
938
|
+
<span class="cline-any cline-no"> </span>
|
|
939
|
+
<span class="cline-any cline-no"> </span>
|
|
940
|
+
<span class="cline-any cline-no"> </span>
|
|
941
|
+
<span class="cline-any cline-no"> </span>
|
|
942
|
+
<span class="cline-any cline-yes">47x</span>
|
|
943
|
+
<span class="cline-any cline-yes">47x</span>
|
|
944
|
+
<span class="cline-any cline-yes">47x</span>
|
|
945
|
+
<span class="cline-any cline-yes">47x</span>
|
|
946
|
+
<span class="cline-any cline-yes">22x</span>
|
|
947
|
+
<span class="cline-any cline-yes">22x</span>
|
|
948
|
+
<span class="cline-any cline-yes">22x</span>
|
|
949
|
+
<span class="cline-any cline-yes">22x</span>
|
|
950
|
+
<span class="cline-any cline-yes">22x</span>
|
|
951
|
+
<span class="cline-any cline-yes">22x</span>
|
|
952
|
+
<span class="cline-any cline-yes">22x</span>
|
|
953
|
+
<span class="cline-any cline-yes">22x</span>
|
|
954
|
+
<span class="cline-any cline-yes">25x</span>
|
|
955
|
+
<span class="cline-any cline-yes">25x</span>
|
|
956
|
+
<span class="cline-any cline-yes">25x</span>
|
|
957
|
+
<span class="cline-any cline-yes">1x</span>
|
|
958
|
+
<span class="cline-any cline-yes">1x</span>
|
|
959
|
+
<span class="cline-any cline-yes">1x</span>
|
|
960
|
+
<span class="cline-any cline-yes">1x</span>
|
|
961
|
+
<span class="cline-any cline-yes">1x</span>
|
|
962
|
+
<span class="cline-any cline-yes">1x</span>
|
|
963
|
+
<span class="cline-any cline-yes">1x</span>
|
|
964
|
+
<span class="cline-any cline-yes">1x</span>
|
|
965
|
+
<span class="cline-any cline-yes">1x</span>
|
|
966
|
+
<span class="cline-any cline-yes">1x</span>
|
|
967
|
+
<span class="cline-any cline-yes">1x</span>
|
|
968
|
+
<span class="cline-any cline-yes">1x</span>
|
|
969
|
+
<span class="cline-any cline-yes">1x</span>
|
|
970
|
+
<span class="cline-any cline-yes">35x</span>
|
|
971
|
+
<span class="cline-any cline-yes">35x</span>
|
|
972
|
+
<span class="cline-any cline-yes">2x</span>
|
|
973
|
+
<span class="cline-any cline-yes">2x</span>
|
|
974
|
+
<span class="cline-any cline-yes">33x</span>
|
|
975
|
+
<span class="cline-any cline-yes">33x</span>
|
|
976
|
+
<span class="cline-any cline-neutral"> </span></td><td class="text"><pre class="prettyprint lang-js">import React, { createContext, useContext, useEffect, useState, useMemo, useCallback } from "react";
|
|
977
|
+
import { translationService } from "../services/translationService";
|
|
978
|
+
import { CRITICAL_TRANSLATIONS } from "../translations/critical";
|
|
979
|
+
import { resolveConfig } from "../utils/configResolver";
|
|
980
|
+
import { logger } from "../utils/logger";
|
|
981
|
+
|
|
982
|
+
// Global flag to prevent duplicate fetch calls across multiple provider instances
|
|
983
|
+
let globalFetchPromise: Promise<Record<string, Record<string, string>>> | null = null;
|
|
984
|
+
let globalFetchInProgress = false;
|
|
985
|
+
|
|
986
|
+
/** i18next instance interface for auto-syncing translations */
|
|
987
|
+
export interface I18nInstance {
|
|
988
|
+
addResourceBundle: (lang: string, ns: string, resources: Record<string, string>, deep?: boolean, overwrite?: boolean) => void;
|
|
989
|
+
language?: string;
|
|
990
|
+
changeLanguage?: (lang: string) => void;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
export interface TranslationsProviderProps {
|
|
994
|
+
children: React.ReactNode;
|
|
995
|
+
apiKey?: string;
|
|
996
|
+
crudifyEnv?: "dev" | "stg" | "api" | "prod";
|
|
997
|
+
featureKeys?: string[];
|
|
998
|
+
language?: string; // Current language (for i18next integration)
|
|
999
|
+
devTranslations?: Record<string, string>; // Props override (dev/testing)
|
|
1000
|
+
translationUrl?: string; // URL to fetch translation overrides
|
|
1001
|
+
enableDebug?: boolean;
|
|
1002
|
+
skipAutoInit?: boolean; // Skip automatic crudify initialization (app is responsible for init)
|
|
1003
|
+
autoSyncI18n?: boolean; // Auto-sync translations with i18next (default: true)
|
|
1004
|
+
i18nInstance?: I18nInstance; // i18next instance for auto-syncing translations
|
|
1005
|
+
loadingFallback?: React.ReactNode; // Optional loading component for initial load
|
|
1006
|
+
waitForInitialLoad?: boolean; // Wait for translations on first load (default: true)
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
export interface TranslationsContextValue {
|
|
1010
|
+
t: (key: string, variables?: Record<string, string | number>) => string;
|
|
1011
|
+
language: string;
|
|
1012
|
+
availableLanguages: string[];
|
|
1013
|
+
translations: Record<string, Record<string, string>>;
|
|
1014
|
+
isLoading: boolean;
|
|
1015
|
+
error: string | null;
|
|
1016
|
+
refreshTranslations: () => Promise<void>;
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
const TranslationsContext = createContext<TranslationsContextValue | null>(null);
|
|
1020
|
+
|
|
1021
|
+
/**
|
|
1022
|
+
* Merge translations with prioritization
|
|
1023
|
+
* Priority (lowest to highest):
|
|
1024
|
+
* 1. Critical bundle (fallback)
|
|
1025
|
+
* 2. API translations (system + subscriber merged by backend, then merged with URL translations by service)
|
|
1026
|
+
* 3. Dev translations (props - only for development/testing)
|
|
1027
|
+
*/
|
|
1028
|
+
function mergeTranslations(
|
|
1029
|
+
critical: Record<string, string>,
|
|
1030
|
+
api: Record<string, string>,
|
|
1031
|
+
dev?: Record<string, string>
|
|
1032
|
+
): Record<string, string> {
|
|
1033
|
+
return {
|
|
1034
|
+
...critical,
|
|
1035
|
+
...api,
|
|
1036
|
+
...(dev || {}),
|
|
1037
|
+
};
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
/**
|
|
1041
|
+
* Hook for auto-syncing translations with i18next
|
|
1042
|
+
* Automatically detects and syncs with i18next instance
|
|
1043
|
+
*/
|
|
1044
|
+
function useI18nAutoSync(
|
|
1045
|
+
translations: Record<string, Record<string, string>>,
|
|
1046
|
+
language: string,
|
|
1047
|
+
i18nInstance: I18nInstance | undefined,
|
|
1048
|
+
enabled: boolean,
|
|
1049
|
+
enableDebug: boolean
|
|
1050
|
+
) {
|
|
1051
|
+
useEffect(() => {
|
|
1052
|
+
if (!enabled || !translations || !language) {
|
|
1053
|
+
return;
|
|
1054
|
+
}
|
|
1055
|
+
|
|
1056
|
+
// Try to detect i18next instance
|
|
1057
|
+
const i18n = i18nInstance || (typeof window !== "undefined" && window.i18next) || (typeof window !== "undefined" && window.i18n);
|
|
1058
|
+
|
|
1059
|
+
if (!i18n || !i18n.addResourceBundle) {
|
|
1060
|
+
if (enableDebug) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
1061
|
+
<span class="cstat-no" title="statement not covered" > logger.debug("[TranslationsProvider] i18next not found, skipping auto-sync");</span>
|
|
1062
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1063
|
+
return;
|
|
1064
|
+
}
|
|
1065
|
+
|
|
1066
|
+
if (enableDebug) {
|
|
1067
|
+
logger.debug("[TranslationsProvider] Auto-syncing translations with i18next", {
|
|
1068
|
+
languages: Object.keys(translations),
|
|
1069
|
+
currentLanguage: language,
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1073
|
+
// Add translations to i18next for all available languages
|
|
1074
|
+
Object.keys(translations).forEach((lang) => {
|
|
1075
|
+
if (translations[lang] && Object.keys(translations[lang]).length > 0) {
|
|
1076
|
+
i18n.addResourceBundle(lang, "translation", translations[lang], true, true);
|
|
1077
|
+
|
|
1078
|
+
if (enableDebug) {
|
|
1079
|
+
logger.debug(`[TranslationsProvider] Synced ${Object.keys(translations[lang]).length} keys for language: ${lang}`);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
});
|
|
1083
|
+
|
|
1084
|
+
// Change language if necessary
|
|
1085
|
+
if (i18n.language !== language && i18n.changeLanguage) {
|
|
1086
|
+
i18n.changeLanguage(language);
|
|
1087
|
+
|
|
1088
|
+
if (enableDebug) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
1089
|
+
<span class="cstat-no" title="statement not covered" > logger.debug(`[TranslationsProvider] Changed i18next language to: ${language}`);</span>
|
|
1090
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1091
|
+
}
|
|
1092
|
+
}, [translations, language, i18nInstance, enabled, enableDebug]);
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
/**
|
|
1096
|
+
* TranslationsProvider
|
|
1097
|
+
*
|
|
1098
|
+
* Provides translation functionality to the application
|
|
1099
|
+
* Handles fetching, caching, and fallback strategies
|
|
1100
|
+
*
|
|
1101
|
+
* Note: The app MUST initialize crudify before mounting TranslationsProvider
|
|
1102
|
+
*
|
|
1103
|
+
* @example Basic usage
|
|
1104
|
+
* ```tsx
|
|
1105
|
+
* // App must initialize crudify first
|
|
1106
|
+
* await crudify.init(publicApiKey, 'debug')
|
|
1107
|
+
*
|
|
1108
|
+
* <TranslationsProvider
|
|
1109
|
+
* apiKey="xxx"
|
|
1110
|
+
* language="es"
|
|
1111
|
+
* translationUrl="https://example.com/locales/es/translation.json"
|
|
1112
|
+
* skipAutoInit={true}
|
|
1113
|
+
* >
|
|
1114
|
+
* <App />
|
|
1115
|
+
* </TranslationsProvider>
|
|
1116
|
+
* ```
|
|
1117
|
+
*
|
|
1118
|
+
* @example With custom loading fallback (recommended for better UX)
|
|
1119
|
+
* ```tsx
|
|
1120
|
+
* <TranslationsProvider
|
|
1121
|
+
* apiKey="xxx"
|
|
1122
|
+
* crudifyEnv="prod"
|
|
1123
|
+
* language={i18n.language}
|
|
1124
|
+
* autoSyncI18n={true}
|
|
1125
|
+
* i18nInstance={i18n}
|
|
1126
|
+
* waitForInitialLoad={true} // Default - waits on first visit
|
|
1127
|
+
* loadingFallback={<LoadingSpinner />} // Custom loading component
|
|
1128
|
+
* >
|
|
1129
|
+
* <App />
|
|
1130
|
+
* </TranslationsProvider>
|
|
1131
|
+
* ```
|
|
1132
|
+
*
|
|
1133
|
+
* @example Disable waiting (legacy behavior - may show keys briefly)
|
|
1134
|
+
* ```tsx
|
|
1135
|
+
* <TranslationsProvider
|
|
1136
|
+
* apiKey="xxx"
|
|
1137
|
+
* language="es"
|
|
1138
|
+
* waitForInitialLoad={false} // Don't wait - render immediately
|
|
1139
|
+
* >
|
|
1140
|
+
* <App />
|
|
1141
|
+
* </TranslationsProvider>
|
|
1142
|
+
* ```
|
|
1143
|
+
*/
|
|
1144
|
+
export const TranslationsProvider: React.FC<TranslationsProviderProps> = ({
|
|
1145
|
+
children,
|
|
1146
|
+
apiKey: propsApiKey,
|
|
1147
|
+
crudifyEnv: propsEnv = "prod",
|
|
1148
|
+
featureKeys: propsFeatureKeys,
|
|
1149
|
+
language = "es",
|
|
1150
|
+
devTranslations,
|
|
1151
|
+
translationUrl,
|
|
1152
|
+
enableDebug = false,
|
|
1153
|
+
skipAutoInit = true, // Default true - assumes app handles crudify.init()
|
|
1154
|
+
autoSyncI18n = true, // Default true - auto-sync with i18next
|
|
1155
|
+
i18nInstance,
|
|
1156
|
+
loadingFallback,
|
|
1157
|
+
waitForInitialLoad = true, // Default true - wait for first load to prevent showing keys
|
|
1158
|
+
}) => {
|
|
1159
|
+
// Resolve configuration using configResolver (cookies > props)
|
|
1160
|
+
// This ensures TranslationsProvider uses the same config as CrudifyInitializer/SessionProvider
|
|
1161
|
+
const resolvedConfig = useMemo(() => {
|
|
1162
|
+
return resolveConfig({
|
|
1163
|
+
publicApiKey: propsApiKey,
|
|
1164
|
+
env: propsEnv,
|
|
1165
|
+
featureKeys: propsFeatureKeys,
|
|
1166
|
+
enableDebug,
|
|
1167
|
+
});
|
|
1168
|
+
}, [propsApiKey, propsEnv, propsFeatureKeys, enableDebug]);
|
|
1169
|
+
|
|
1170
|
+
const apiKey = resolvedConfig.<span class="branch-0 cbranch-no" title="branch not covered" >publicApiKey || "";</span>
|
|
1171
|
+
const crudifyEnv = resolvedConfig.<span class="branch-0 cbranch-no" title="branch not covered" >env || <span class="branch-0 cbranch-no" title="branch not covered" >propsEnv || "</span>prod";</span>
|
|
1172
|
+
const featureKeys = resolvedConfig.featureKeys || propsFeatureKeys;
|
|
1173
|
+
|
|
1174
|
+
const [translations, setTranslations] = useState<Record<string, Record<string, string>>>({});
|
|
1175
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
1176
|
+
const [isInitialLoad, setIsInitialLoad] = useState(true); // Track if this is the first load
|
|
1177
|
+
const [error, setError] = useState<string | null>(null);
|
|
1178
|
+
const [urlTranslations, setUrlTranslations] = useState<Record<string, string> | undefined>(undefined);
|
|
1179
|
+
const [hasFailedPermanently, setHasFailedPermanently] = useState(false);
|
|
1180
|
+
|
|
1181
|
+
// Load translations
|
|
1182
|
+
const loadTranslations = useCallback(async () => {
|
|
1183
|
+
// Skip if no apiKey available
|
|
1184
|
+
if (!apiKey) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
1185
|
+
<span class="cstat-no" title="statement not covered" > if (enableDebug) logger.debug("[TranslationsProvider] No apiKey - skipping translation fetch");</span>
|
|
1186
|
+
<span class="cstat-no" title="statement not covered" > setIsLoading(false);</span>
|
|
1187
|
+
<span class="cstat-no" title="statement not covered" > setIsInitialLoad(false);</span>
|
|
1188
|
+
<span class="cstat-no" title="statement not covered" > return;</span>
|
|
1189
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1190
|
+
|
|
1191
|
+
// Skip if already failed permanently
|
|
1192
|
+
if (hasFailedPermanently) {
|
|
1193
|
+
if (enableDebug) <span class="branch-0 cbranch-no" title="branch not covered" >logger.debug("[TranslationsProvider] Skipping reload - using fallback translations");</span>
|
|
1194
|
+
return;
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
// Check if we have valid cache before starting the load
|
|
1198
|
+
// This allows us to render immediately with cached data on subsequent visits
|
|
1199
|
+
const hasValidCache = translationService.hasValidCache(apiKey);
|
|
1200
|
+
if (<span class="branch-0 cbranch-no" title="branch not covered" >hasValidCache && isInitialLoad) <span class="branch-0 cbranch-no" title="branch not covered" >{</span></span>
|
|
1201
|
+
<span class="cstat-no" title="statement not covered" > if (enableDebug) logger.debug("[TranslationsProvider] Valid cache found - not blocking initial render");</span>
|
|
1202
|
+
<span class="cstat-no" title="statement not covered" > setIsInitialLoad(false); // We have cache, so not truly initial</span>
|
|
1203
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1204
|
+
|
|
1205
|
+
// Global lock: Prevent duplicate fetches across multiple provider instances
|
|
1206
|
+
if (<span class="branch-0 cbranch-no" title="branch not covered" >globalFetchInProgress && globalFetchPromise) <span class="branch-0 cbranch-no" title="branch not covered" >{</span></span>
|
|
1207
|
+
<span class="cstat-no" title="statement not covered" > if (enableDebug) logger.debug("[TranslationsProvider] Fetch already in progress, waiting for existing promise");</span>
|
|
1208
|
+
<span class="cstat-no" title="statement not covered" > try {</span>
|
|
1209
|
+
<span class="cstat-no" title="statement not covered" > const result = await globalFetchPromise;</span>
|
|
1210
|
+
<span class="cstat-no" title="statement not covered" > setTranslations(result);</span>
|
|
1211
|
+
<span class="cstat-no" title="statement not covered" > setIsLoading(false);</span>
|
|
1212
|
+
<span class="cstat-no" title="statement not covered" > return;</span>
|
|
1213
|
+
<span class="cstat-no" title="statement not covered" > } catch (err) {</span>
|
|
1214
|
+
<span class="cstat-no" title="statement not covered" > // If global fetch failed, fall through to try again</span>
|
|
1215
|
+
<span class="cstat-no" title="statement not covered" > if (enableDebug) logger.warn("[TranslationsProvider] Global fetch failed, retrying");</span>
|
|
1216
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1217
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1218
|
+
|
|
1219
|
+
// Mark fetch as in progress
|
|
1220
|
+
globalFetchInProgress = true;
|
|
1221
|
+
|
|
1222
|
+
setIsLoading(true);
|
|
1223
|
+
setError(null);
|
|
1224
|
+
|
|
1225
|
+
// Fetch translations from URL if provided
|
|
1226
|
+
let fetchedUrlTranslations: Record<string, string> | undefined = undefined;
|
|
1227
|
+
|
|
1228
|
+
if (translationUrl) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
1229
|
+
<span class="cstat-no" title="statement not covered" > try {</span>
|
|
1230
|
+
<span class="cstat-no" title="statement not covered" > if (enableDebug) {</span>
|
|
1231
|
+
<span class="cstat-no" title="statement not covered" > logger.debug(`[TranslationsProvider] Fetching translations from URL: ${translationUrl}`);</span>
|
|
1232
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1233
|
+
<span class="cstat-no" title="statement not covered" ></span>
|
|
1234
|
+
<span class="cstat-no" title="statement not covered" > const response = await fetch(translationUrl);</span>
|
|
1235
|
+
<span class="cstat-no" title="statement not covered" > if (!response.ok) {</span>
|
|
1236
|
+
<span class="cstat-no" title="statement not covered" > throw new Error(`Failed to fetch translations: ${response.statusText}`);</span>
|
|
1237
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1238
|
+
<span class="cstat-no" title="statement not covered" ></span>
|
|
1239
|
+
<span class="cstat-no" title="statement not covered" > fetchedUrlTranslations = await response.json();</span>
|
|
1240
|
+
<span class="cstat-no" title="statement not covered" > setUrlTranslations(fetchedUrlTranslations);</span>
|
|
1241
|
+
<span class="cstat-no" title="statement not covered" ></span>
|
|
1242
|
+
<span class="cstat-no" title="statement not covered" > if (enableDebug) {</span>
|
|
1243
|
+
<span class="cstat-no" title="statement not covered" > logger.debug("[TranslationsProvider] URL translations loaded:", {</span>
|
|
1244
|
+
<span class="cstat-no" title="statement not covered" > keysCount: fetchedUrlTranslations ? Object.keys(fetchedUrlTranslations).length : 0,</span>
|
|
1245
|
+
<span class="cstat-no" title="statement not covered" > });</span>
|
|
1246
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1247
|
+
<span class="cstat-no" title="statement not covered" > } catch (err: unknown) {</span>
|
|
1248
|
+
<span class="cstat-no" title="statement not covered" > logger.error("[TranslationsProvider] Failed to load URL translations", err instanceof Error ? err : { message: String(err) });</span>
|
|
1249
|
+
<span class="cstat-no" title="statement not covered" > fetchedUrlTranslations = undefined;</span>
|
|
1250
|
+
<span class="cstat-no" title="statement not covered" > setUrlTranslations(undefined);</span>
|
|
1251
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1252
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1253
|
+
|
|
1254
|
+
// Wrap the main fetch in a global promise
|
|
1255
|
+
const fetchPromise = (async () => {
|
|
1256
|
+
try {
|
|
1257
|
+
// Set debug mode for translation service
|
|
1258
|
+
translationService.setDebug(enableDebug);
|
|
1259
|
+
|
|
1260
|
+
// Fetch dynamic translations (system + subscriber + URL merged by service)
|
|
1261
|
+
const dynamicTranslations = await translationService.fetchTranslations({
|
|
1262
|
+
apiKey,
|
|
1263
|
+
crudifyEnv,
|
|
1264
|
+
featureKeys,
|
|
1265
|
+
urlTranslations: fetchedUrlTranslations,
|
|
1266
|
+
});
|
|
1267
|
+
|
|
1268
|
+
// Merge with prioritization
|
|
1269
|
+
const merged: Record<string, Record<string, string>> = {};
|
|
1270
|
+
|
|
1271
|
+
Object.keys(dynamicTranslations).forEach((lang) => {
|
|
1272
|
+
const critical = (CRITICAL_TRANSLATIONS[lang as keyof typeof CRITICAL_TRANSLATIONS<span class="branch-0 cbranch-no" title="branch not covered" >] as Record<string, string>) || {};</span>
|
|
1273
|
+
const fromAPI = dynamicTranslations[lang<span class="branch-0 cbranch-no" title="branch not covered" >] || {};</span>
|
|
1274
|
+
// Note: fromAPI already contains system + subscriber + URL merged
|
|
1275
|
+
|
|
1276
|
+
merged[lang] = mergeTranslations(critical, fromAPI, devTranslations);
|
|
1277
|
+
});
|
|
1278
|
+
|
|
1279
|
+
if (enableDebug) {
|
|
1280
|
+
logger.debug("[TranslationsProvider] Loaded translations:", {
|
|
1281
|
+
languages: Object.keys(merged),
|
|
1282
|
+
keysCount: Object.keys(merged[language<span class="branch-0 cbranch-no" title="branch not covered" >] || {})</span>.length,
|
|
1283
|
+
});
|
|
1284
|
+
}
|
|
1285
|
+
|
|
1286
|
+
return merged;
|
|
1287
|
+
} catch (err: unknown) {
|
|
1288
|
+
logger.error("[TranslationsProvider] Failed to load", err instanceof Error ? <span class="branch-0 cbranch-no" title="branch not covered" >err : { message: String(err) })</span>;
|
|
1289
|
+
setError(err instanceof Error ? err.<span class="branch-0 cbranch-no" title="branch not covered" >message : String(err))</span>;
|
|
1290
|
+
setHasFailedPermanently(true); // Mark as failed permanently to prevent retries
|
|
1291
|
+
|
|
1292
|
+
// Fallback: critical bundle + URL translations + dev overrides
|
|
1293
|
+
const fallback: Record<string, Record<string, string>> = {};
|
|
1294
|
+
Object.keys(CRITICAL_TRANSLATIONS).forEach((lang) => {
|
|
1295
|
+
const critical = CRITICAL_TRANSLATIONS[lang as keyof typeof CRITICAL_TRANSLATIONS] as Record<string, string>;
|
|
1296
|
+
|
|
1297
|
+
// If we have URL translations, use them as fallback (they have priority over critical)
|
|
1298
|
+
// Use fetchedUrlTranslations if just loaded, otherwise use state urlTranslations
|
|
1299
|
+
const urlFallback = fetchedUrlTranslations || urlTranslations || {};
|
|
1300
|
+
|
|
1301
|
+
fallback[lang] = mergeTranslations(critical, urlFallback, devTranslations);
|
|
1302
|
+
});
|
|
1303
|
+
|
|
1304
|
+
if (enableDebug) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
1305
|
+
<span class="cstat-no" title="statement not covered" > logger.debug("[TranslationsProvider] Using fallback translations (critical + URL)");</span>
|
|
1306
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1307
|
+
|
|
1308
|
+
return fallback;
|
|
1309
|
+
}
|
|
1310
|
+
})();
|
|
1311
|
+
|
|
1312
|
+
// Store as global promise
|
|
1313
|
+
globalFetchPromise = fetchPromise;
|
|
1314
|
+
|
|
1315
|
+
try {
|
|
1316
|
+
const result = await fetchPromise;
|
|
1317
|
+
setTranslations(result);
|
|
1318
|
+
} finally {
|
|
1319
|
+
setIsLoading(false);
|
|
1320
|
+
setIsInitialLoad(false); // Mark that initial load is complete
|
|
1321
|
+
// Clear global flag after fetch completes
|
|
1322
|
+
globalFetchInProgress = false;
|
|
1323
|
+
// Clear promise after a delay to allow other instances to catch it
|
|
1324
|
+
setTimeout(() => {
|
|
1325
|
+
globalFetchPromise = null;
|
|
1326
|
+
}, 1000);
|
|
1327
|
+
}
|
|
1328
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1329
|
+
}, [apiKey, crudifyEnv, featureKeys, translationUrl, devTranslations, enableDebug, language, hasFailedPermanently]);
|
|
1330
|
+
|
|
1331
|
+
useEffect(() => {
|
|
1332
|
+
loadTranslations();
|
|
1333
|
+
|
|
1334
|
+
// Auto-refresh every hour
|
|
1335
|
+
const interval = setInterval(loadTranslations, 60 * 60 * 1000);
|
|
1336
|
+
|
|
1337
|
+
return () => clearInterval(interval);
|
|
1338
|
+
}, [loadTranslations]);
|
|
1339
|
+
|
|
1340
|
+
// Translation function with variable interpolation
|
|
1341
|
+
const t = useMemo(() => {
|
|
1342
|
+
return (key: string, variables?: Record<string, string | number>) => {
|
|
1343
|
+
const currentLang = translations[language<span class="branch-0 cbranch-no" title="branch not covered" >] || {};</span>
|
|
1344
|
+
let value = currentLang[key];
|
|
1345
|
+
|
|
1346
|
+
// Fallback: search in other languages
|
|
1347
|
+
if (!value) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
1348
|
+
<span class="cstat-no" title="statement not covered" > const allLangs = Object.keys(translations);</span>
|
|
1349
|
+
<span class="cstat-no" title="statement not covered" > for (const lang of allLangs) {</span>
|
|
1350
|
+
<span class="cstat-no" title="statement not covered" > if (translations[lang][key]) {</span>
|
|
1351
|
+
<span class="cstat-no" title="statement not covered" > value = translations[lang][key];</span>
|
|
1352
|
+
<span class="cstat-no" title="statement not covered" > break;</span>
|
|
1353
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1354
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1355
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1356
|
+
|
|
1357
|
+
// If not found, return key
|
|
1358
|
+
if (!value) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
1359
|
+
<span class="cstat-no" title="statement not covered" > if (enableDebug) logger.warn(`[TranslationsProvider] Missing translation: "${key}"`);</span>
|
|
1360
|
+
<span class="cstat-no" title="statement not covered" > value = key;</span>
|
|
1361
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1362
|
+
|
|
1363
|
+
// Replace variables
|
|
1364
|
+
if (variables && typeof value === "string") {
|
|
1365
|
+
Object.entries(variables).forEach(([varKey, varValue]) => {
|
|
1366
|
+
const regex = new RegExp(`{{${varKey}}}`, "g");
|
|
1367
|
+
value = (value as string).replace(regex, String(varValue));
|
|
1368
|
+
});
|
|
1369
|
+
}
|
|
1370
|
+
|
|
1371
|
+
return value as string;
|
|
1372
|
+
};
|
|
1373
|
+
}, [translations, language, enableDebug]);
|
|
1374
|
+
|
|
1375
|
+
// Auto-sync translations with i18next
|
|
1376
|
+
useI18nAutoSync(translations, language, i18nInstance, autoSyncI18n, enableDebug);
|
|
1377
|
+
|
|
1378
|
+
const contextValue: TranslationsContextValue = {
|
|
1379
|
+
t,
|
|
1380
|
+
language,
|
|
1381
|
+
availableLanguages: Object.keys(translations),
|
|
1382
|
+
translations,
|
|
1383
|
+
isLoading,
|
|
1384
|
+
error,
|
|
1385
|
+
refreshTranslations: loadTranslations,
|
|
1386
|
+
};
|
|
1387
|
+
|
|
1388
|
+
// Early validation: If no apiKey available, skip translations but render children
|
|
1389
|
+
if (!apiKey) <span class="branch-0 cbranch-no" title="branch not covered" >{</span>
|
|
1390
|
+
<span class="cstat-no" title="statement not covered" > if (enableDebug) {</span>
|
|
1391
|
+
<span class="cstat-no" title="statement not covered" > logger.warn(</span>
|
|
1392
|
+
<span class="cstat-no" title="statement not covered" > "[TranslationsProvider] No API key available. Skipping translations. Provide apiKey via props or ensure cookies are set by Lambda."</span>
|
|
1393
|
+
<span class="cstat-no" title="statement not covered" > );</span>
|
|
1394
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1395
|
+
<span class="cstat-no" title="statement not covered" > return <>{children}</>;</span>
|
|
1396
|
+
<span class="cstat-no" title="statement not covered" > }</span>
|
|
1397
|
+
|
|
1398
|
+
// Block rendering on initial load to prevent showing translation keys
|
|
1399
|
+
// On subsequent loads (cache available), render immediately and update in background
|
|
1400
|
+
if (waitForInitialLoad && isInitialLoad && isLoading) {
|
|
1401
|
+
return (
|
|
1402
|
+
loadingFallback || (
|
|
1403
|
+
<div style={{ display: "flex", justifyContent: "center", alignItems: "center", height: "100vh" }}>
|
|
1404
|
+
<div>Loading translations...</div>
|
|
1405
|
+
</div>
|
|
1406
|
+
)
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
return <TranslationsContext.Provider value={contextValue}>{children}</TranslationsContext.Provider>;
|
|
1411
|
+
};
|
|
1412
|
+
|
|
1413
|
+
/**
|
|
1414
|
+
* Hook to use translations
|
|
1415
|
+
*
|
|
1416
|
+
* @example
|
|
1417
|
+
* ```tsx
|
|
1418
|
+
* const MyComponent = () => {
|
|
1419
|
+
* const { t } = useTranslations();
|
|
1420
|
+
* return <h1>{t('welcome.title')}</h1>;
|
|
1421
|
+
* };
|
|
1422
|
+
* ```
|
|
1423
|
+
*/
|
|
1424
|
+
export const useTranslations = (): TranslationsContextValue => {
|
|
1425
|
+
const context = useContext(TranslationsContext);
|
|
1426
|
+
if (!context) {
|
|
1427
|
+
throw new Error("useTranslations must be used within TranslationsProvider");
|
|
1428
|
+
}
|
|
1429
|
+
return context;
|
|
1430
|
+
};
|
|
1431
|
+
</pre></td></tr></table></pre>
|
|
1432
|
+
|
|
1433
|
+
<div class='push'></div><!-- for sticky footer -->
|
|
1434
|
+
</div><!-- /wrapper -->
|
|
1435
|
+
<div class='footer quiet pad2 space-top1 center small'>
|
|
1436
|
+
Code coverage generated by
|
|
1437
|
+
<a href="https://istanbul.js.org/" target="_blank" rel="noopener noreferrer">istanbul</a>
|
|
1438
|
+
at 2026-01-28T06:22:15.683Z
|
|
1439
|
+
</div>
|
|
1440
|
+
<script src="../prettify.js"></script>
|
|
1441
|
+
<script>
|
|
1442
|
+
window.onload = function () {
|
|
1443
|
+
prettyPrint();
|
|
1444
|
+
};
|
|
1445
|
+
</script>
|
|
1446
|
+
<script src="../sorter.js"></script>
|
|
1447
|
+
<script src="../block-navigation.js"></script>
|
|
1448
|
+
</body>
|
|
1449
|
+
</html>
|
|
1450
|
+
|