|
35 | 35 | <RadzenFormField Text="Format" Variant="Radzen.Variant.Outlined" Style="width: 100%;"> |
36 | 36 | <ChildContent> |
37 | 37 | <RadzenDropDown @bind-Value="_model.Format" Style="width: 100%;" |
38 | | - Data="@_formatOptions" TextProperty="Text" ValueProperty="Value" |
39 | | - Disabled="@_isSubmitting" /> |
| 38 | + Data="@_formatDropdownOptions" TextProperty="Text" ValueProperty="Value" |
| 39 | + Disabled="@_isSubmitting" Change="@OnFormatChanged" /> |
40 | 40 | </ChildContent> |
41 | 41 | </RadzenFormField> |
42 | 42 |
|
|
60 | 60 | </Helper> |
61 | 61 | </RadzenFormField> |
62 | 62 |
|
| 63 | + @* Format-specific options *@ |
| 64 | + @if (HasFormatOptions) |
| 65 | + { |
| 66 | + <details open="@_formatOptionsOpen"> |
| 67 | + <summary style="cursor: pointer; font-weight: 500; margin-bottom: 0.5rem;" @onclick="() => _formatOptionsOpen = !_formatOptionsOpen">Format Options</summary> |
| 68 | + <RadzenStack Gap="0.75rem" Style="margin-top: 0.5rem;"> |
| 69 | + @switch (_model.Format) |
| 70 | + { |
| 71 | + case "po": |
| 72 | + <RadzenFormField Text="Domain" Variant="Radzen.Variant.Outlined" Style="width: 100%;"> |
| 73 | + <ChildContent> |
| 74 | + <RadzenTextBox @bind-Value="_formatOptions.PoDomain" Placeholder="messages" |
| 75 | + Disabled="@_isSubmitting" Style="width: 100%;" /> |
| 76 | + </ChildContent> |
| 77 | + <Helper> |
| 78 | + <RadzenText TextStyle="TextStyle.Caption" class="rz-color-secondary">PO file domain name (e.g., messages, django)</RadzenText> |
| 79 | + </Helper> |
| 80 | + </RadzenFormField> |
| 81 | + <RadzenFormField Text="Folder Structure" Variant="Radzen.Variant.Outlined" Style="width: 100%;"> |
| 82 | + <ChildContent> |
| 83 | + <RadzenDropDown @bind-Value="_formatOptions.PoFolderStructure" Style="width: 100%;" |
| 84 | + Data="@_poFolderOptions" TextProperty="Text" ValueProperty="Value" |
| 85 | + Disabled="@_isSubmitting" /> |
| 86 | + </ChildContent> |
| 87 | + <Helper> |
| 88 | + <RadzenText TextStyle="TextStyle.Caption" class="rz-color-secondary">GNU: locale/{'{'}lang{'}'}/LC_MESSAGES/, Flat: po/{'{'}lang{'}'}.po</RadzenText> |
| 89 | + </Helper> |
| 90 | + </RadzenFormField> |
| 91 | + <RadzenFormField Text="Key Strategy" Variant="Radzen.Variant.Outlined" Style="width: 100%;"> |
| 92 | + <ChildContent> |
| 93 | + <RadzenDropDown @bind-Value="_formatOptions.PoKeyStrategy" Style="width: 100%;" |
| 94 | + Data="@_poKeyStrategyOptions" TextProperty="Text" ValueProperty="Value" |
| 95 | + Disabled="@_isSubmitting" /> |
| 96 | + </ChildContent> |
| 97 | + <Helper> |
| 98 | + <RadzenText TextStyle="TextStyle.Caption" class="rz-color-secondary">How to derive keys from PO entries</RadzenText> |
| 99 | + </Helper> |
| 100 | + </RadzenFormField> |
| 101 | + break; |
| 102 | + |
| 103 | + case "xliff": |
| 104 | + <RadzenFormField Text="XLIFF Version" Variant="Radzen.Variant.Outlined" Style="width: 100%;"> |
| 105 | + <ChildContent> |
| 106 | + <RadzenDropDown @bind-Value="_formatOptions.XliffVersion" Style="width: 100%;" |
| 107 | + Data="@_xliffVersionOptions" TextProperty="Text" ValueProperty="Value" |
| 108 | + Disabled="@_isSubmitting" /> |
| 109 | + </ChildContent> |
| 110 | + </RadzenFormField> |
| 111 | + <RadzenStack Orientation="Radzen.Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem"> |
| 112 | + <RadzenCheckBox @bind-Value="_formatOptions.XliffBilingual" Disabled="@_isSubmitting" /> |
| 113 | + <RadzenText>Bilingual files (include source text in all files)</RadzenText> |
| 114 | + </RadzenStack> |
| 115 | + break; |
| 116 | + |
| 117 | + case "json": |
| 118 | + <RadzenStack Orientation="Radzen.Orientation.Horizontal" AlignItems="AlignItems.Center" Gap="0.5rem"> |
| 119 | + <RadzenCheckBox @bind-Value="_formatOptions.JsonNestedKeys" Disabled="@_isSubmitting" /> |
| 120 | + <RadzenText>Use nested keys (e.g., common.buttons.save)</RadzenText> |
| 121 | + </RadzenStack> |
| 122 | + break; |
| 123 | + |
| 124 | + case "resx": |
| 125 | + case "android": |
| 126 | + case "ios": |
| 127 | + <RadzenFormField Text="Base Filename" Variant="Radzen.Variant.Outlined" Style="width: 100%;"> |
| 128 | + <ChildContent> |
| 129 | + <RadzenTextBox @bind-Value="_formatOptions.BaseName" Placeholder="@GetDefaultBaseName()" |
| 130 | + Disabled="@_isSubmitting" Style="width: 100%;" /> |
| 131 | + </ChildContent> |
| 132 | + <Helper> |
| 133 | + <RadzenText TextStyle="TextStyle.Caption" class="rz-color-secondary">@GetBaseNameHelp()</RadzenText> |
| 134 | + </Helper> |
| 135 | + </RadzenFormField> |
| 136 | + break; |
| 137 | + } |
| 138 | + </RadzenStack> |
| 139 | + </details> |
| 140 | + } |
| 141 | + |
63 | 142 | <details> |
64 | 143 | <summary style="cursor: pointer; font-weight: 500; margin-bottom: 0.5rem;">GitHub Integration (Optional)</summary> |
65 | 144 | <RadzenStack Gap="1rem" Style="margin-top: 0.5rem;"> |
|
106 | 185 | public EventCallback<ProjectDto> OnProjectCreated { get; set; } |
107 | 186 |
|
108 | 187 | private bool _isSubmitting; |
| 188 | + private bool _formatOptionsOpen = true; |
109 | 189 | private string? _errorMessage; |
110 | 190 | private CreateProjectRequest _model = new() { Slug = "", Name = "", Format = "resx", DefaultLanguage = "en", LocalizationPath = "." }; |
| 191 | + private FormatOptionsDto _formatOptions = new(); |
111 | 192 |
|
112 | | - private readonly List<object> _formatOptions = new() |
| 193 | + private readonly List<object> _formatDropdownOptions = new() |
113 | 194 | { |
114 | 195 | new { Value = "resx", Text = ".resx (C#/.NET)" }, |
115 | 196 | new { Value = "json", Text = "JSON Localization" }, |
116 | 197 | new { Value = "i18next", Text = "i18next (JS/React)" }, |
117 | 198 | new { Value = "android", Text = "Android strings.xml" }, |
118 | | - new { Value = "ios", Text = "iOS .strings/.stringsdict" } |
| 199 | + new { Value = "ios", Text = "iOS .strings/.stringsdict" }, |
| 200 | + new { Value = "po", Text = "GNU gettext (.po/.pot)" }, |
| 201 | + new { Value = "xliff", Text = "XLIFF (.xliff/.xlf)" } |
| 202 | + }; |
| 203 | + |
| 204 | + private readonly List<object> _poFolderOptions = new() |
| 205 | + { |
| 206 | + new { Value = "gnu", Text = "GNU (locale/{lang}/LC_MESSAGES/)" }, |
| 207 | + new { Value = "flat", Text = "Flat (po/{lang}.po)" } |
| 208 | + }; |
| 209 | + |
| 210 | + private readonly List<object> _poKeyStrategyOptions = new() |
| 211 | + { |
| 212 | + new { Value = "auto", Text = "Auto (context if available, else msgid)" }, |
| 213 | + new { Value = "msgid", Text = "Use msgid (source text as key)" }, |
| 214 | + new { Value = "context", Text = "Use msgctxt (context as key)" } |
| 215 | + }; |
| 216 | + |
| 217 | + private readonly List<object> _xliffVersionOptions = new() |
| 218 | + { |
| 219 | + new { Value = "2.0", Text = "XLIFF 2.0 (Recommended)" }, |
| 220 | + new { Value = "1.2", Text = "XLIFF 1.2 (Legacy)" } |
| 221 | + }; |
| 222 | + |
| 223 | + private bool HasFormatOptions => _model.Format is "po" or "xliff" or "json" or "resx" or "android" or "ios"; |
| 224 | + |
| 225 | + private void OnFormatChanged(object value) |
| 226 | + { |
| 227 | + // Reset format options when format changes |
| 228 | + _formatOptions = new FormatOptionsDto |
| 229 | + { |
| 230 | + PoFolderStructure = "gnu", |
| 231 | + PoKeyStrategy = "auto", |
| 232 | + XliffVersion = "2.0" |
| 233 | + }; |
| 234 | + StateHasChanged(); |
| 235 | + } |
| 236 | + |
| 237 | + private string GetDefaultBaseName() => _model.Format switch |
| 238 | + { |
| 239 | + "resx" => "SharedResource", |
| 240 | + "android" => "strings", |
| 241 | + "ios" => "Localizable", |
| 242 | + _ => "" |
| 243 | + }; |
| 244 | + |
| 245 | + private string GetBaseNameHelp() => _model.Format switch |
| 246 | + { |
| 247 | + "resx" => "e.g., SharedResource, Resources, Strings", |
| 248 | + "android" => "e.g., strings, messages", |
| 249 | + "ios" => "e.g., Localizable, InfoPlist", |
| 250 | + _ => "" |
119 | 251 | }; |
120 | 252 |
|
121 | 253 | private void Close() |
|
130 | 262 |
|
131 | 263 | try |
132 | 264 | { |
| 265 | + // Attach format options to the model |
| 266 | + _model.FormatOptions = _formatOptions; |
133 | 267 | var result = await ProjectService.CreateProjectAsync(_model); |
134 | 268 |
|
135 | 269 | if (result.IsSuccess && result.Data != null) |
|
0 commit comments