Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,17 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

- BREAKING CHANGE: [L10NSharp] [L10NSharp.Windows.Forms] [SampleApp] [CheckOrFixXliff] [ExtractXliff] Replaced the `net461` target framework with `net462`. The `System.Resources.Extensions` version raised transitively by the `SIL.ReleaseTasks` upgrade (above) no longer ships a `net461`-specific assembly, so `net461` is no longer a supported or tested target. Projects that still need to target `net461` should continue using the last release built for it, or upgrade to at least `net462`.

### Fixed

- [L10NSharp.Windows.Forms] Fixed `LanguageChoosingDialog`'s fail-safe, on-the-fly translation of its title/message/OK button, which had been silently broken since the Bing/Microsoft Translator v1 SOAP API it used was retired. It now uses the free, keyless MyMemory Translation API by default; host apps that want more robust translation can opt in to the new public `MicrosoftTranslator` class (Azure AI Translator v3) by setting a subscription key. See [#163](https://github.com/sillsdev/l10nsharp/issues/163). The SampleApp has a "Show Language Chooser" button so you can see it in action without needing to fake a missing-locale scenario.

### Removed

- [L10NSharp.Windows.Forms] Removed the internal `BingTranslator` class and its generated WCF service reference, along with the `System.ServiceModel`/`System.Security.Cryptography.Xml` dependencies they required, since the API they called has been retired. See "Fixed", above.

### Security

- [L10NSharp] [L10NSharp.Windows.Forms] [CheckOrFixXliff] [ExtractXliff] Upgraded `SIL.ReleaseTasks` from 2.5.0 to 3.3.0. This also raises the resolved version of `System.Resources.Extensions` (a transitive dependency of `SIL.ReleaseTasks`) from 6.0.0 to 10.0.11. Note: `SIL.ReleaseTasks` 3.3.0 has a known, build-time-only dependency on a vulnerable `Newtonsoft.Json` (via a temporary revert of its own `SIL.Core` dependency, pending an upstream `Mono.Unix` packaging issue) — per the upstream maintainers this is not an exploitable runtime risk, since the package is build-tool-only and never ships in L10nSharp's own output, and no L10nSharp or SIL.ReleaseTasks build step feeds it untrusted JSON. See [sillsdev/SIL.BuildTasks#88](https://github.com/sillsdev/SIL.BuildTasks/pull/88) for details.
- [L10NSharp.Windows.Forms] Upgraded `System.ServiceModel.Http` and `System.ServiceModel.Primitives` from 6.2.0 to 8.1.2, and added a direct `System.Security.Cryptography.Xml` reference pinned to 8.0.4. `System.ServiceModel.Primitives` 8.1.2 resolves a vulnerable 8.0.2 of `System.Security.Cryptography.Xml` transitively on `net8.0-windows`; the direct reference overrides it with the latest patched 8.0.x release.

## [10.0.0] - 2026-08-27

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ public void TranslateStrings_RequestedCultureSpanishChokesOnFormatParam_Translat
Assert.AreEqual("No localization for Spanish (español)", model.Message);
var translator = new TestTranslatorSpanishChokesOnFormatParam();
model.TranslateStrings(translator);
// Note: the test translator mimics Bing's behavior of replacing the English name of the requested language with the word "English" in the translation.
// Note: this fake translator's "chokes on {0}, then swaps in the word 'English'" behavior mimics a quirk of the old,
// now-removed BingTranslator. It's kept as a synthetic worst case for the retry-without-format-param fallback path
// below; the current default translator, MyMemoryTranslator, doesn't exhibit either behavior (verified live: it
// preserves a literal "{0}" through translation, and translates rather than substitutes the language name).
Assert.AreEqual("No choke No localization for English (español)", model.Message);
Assert.AreEqual("No choke OK", model.AcceptButtonText);
Assert.AreEqual("No choke Choose a Language", model.WindowTitle);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using L10NSharp.Windows.Forms.Translators;
using NUnit.Framework;

namespace L10NSharp.Windows.Forms.Tests.Translators
{
[TestFixture]
public class MicrosoftTranslatorTests
{
private const string kKeyEnvVar = "L10NSHARP_TRANSLATOR_KEY";
private const string kRegionEnvVar = "L10NSHARP_TRANSLATOR_REGION";

[TearDown]
public void TearDown()
{
MicrosoftTranslator.SubscriptionKey = null;
MicrosoftTranslator.Region = null;
Environment.SetEnvironmentVariable(kKeyEnvVar, null);
Environment.SetEnvironmentVariable(kRegionEnvVar, null);
}

[Test]
public void IsConfigured_NoKeySetAnywhere_ReturnsFalse()
{
Assert.That(MicrosoftTranslator.IsConfigured, Is.False);
}

[Test]
public void IsConfigured_SubscriptionKeySetDirectly_ReturnsTrue()
{
MicrosoftTranslator.SubscriptionKey = "some-key";
Assert.That(MicrosoftTranslator.IsConfigured, Is.True);
}

[Test]
public void IsConfigured_SubscriptionKeySetViaEnvironmentVariable_ReturnsTrue()
{
Environment.SetEnvironmentVariable(kKeyEnvVar, "some-key");
Assert.That(MicrosoftTranslator.IsConfigured, Is.True);
}

[Test]
public void SubscriptionKey_SetDirectly_TakesPrecedenceOverEnvironmentVariable()
{
Environment.SetEnvironmentVariable(kKeyEnvVar, "env-key");
MicrosoftTranslator.SubscriptionKey = "direct-key";
Assert.That(MicrosoftTranslator.EffectiveSubscriptionKey, Is.EqualTo("direct-key"));
}

[Test]
public void Region_NotSetDirectly_FallsBackToEnvironmentVariable()
{
Environment.SetEnvironmentVariable(kRegionEnvVar, "westus");
Assert.That(MicrosoftTranslator.EffectiveRegion, Is.EqualTo("westus"));
}

[Test]
public void Region_NeitherSet_IsNull()
{
Assert.That(MicrosoftTranslator.EffectiveRegion, Is.Null);
}
}
}
9 changes: 0 additions & 9 deletions src/L10NSharp.Windows.Forms/L10NSharp.Windows.Forms.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,8 @@
<SignAssembly>True</SignAssembly>
</PropertyGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net462' Or '$(TargetFramework)' == 'net48' ">
<Reference Include="System.ServiceModel" />
<Reference Include="System.Windows.Forms" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0-windows' ">
<PackageReference Include="System.ServiceModel.Http" Version="8.1.2" />
<PackageReference Include="System.ServiceModel.Primitives" Version="8.1.2" />
<PackageReference Include="System.Security.Cryptography.Xml" Version="8.0.4" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\L10NSharp\L10NSharp.csproj" />
</ItemGroup>
Expand Down Expand Up @@ -74,8 +68,5 @@
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
<Generator>SettingsSingleFileGenerator</Generator>
</None>
<None Update="Service References\BingTranslatorService\Reference.svcmap">
<Generator>WCF Proxy Generator</Generator>
</None>
</ItemGroup>
</Project>

This file was deleted.

This file was deleted.

This file was deleted.

Loading
Loading