Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zh-CN translation: Add translation for platform and hosting #567

Merged
merged 1 commit into from
Nov 1, 2024
Merged
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
4 changes: 4 additions & 0 deletions i18n/zh-Hans/docusaurus-plugin-content-docs/current.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,10 @@
"message": "平台",
"description": "The label for category Platforms in sidebar documentationSidebar"
},
"sidebar.documentationSidebar.category.Platform-Specific Code": {
"message": "特定平台代码",
"description": "The label for category Platform-Specific Code in sidebar documentationSidebar"
},
"sidebar.documentationSidebar.category.Android": {
"message": "Android",
"description": "The label for category Android in sidebar documentationSidebar"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,47 +1,47 @@
---
id: dotnet
title: Platform-Specific .NET
title: 特定平台的.NET
---
## 概述

## Overview
.NET当中的条件编译允许根据某些条件编译或省略代码的不同部分。这对于处理需要在不同平台或开发环境中不同行为的代码时特别有用。

Conditional compilation in .NET allows different parts of the code to be compiled or omitted based on certain conditions. This is particularly useful in .NET when dealing with code that needs to behave differently on various platforms or under different development environments.
这些方案并不特定于Avalonia,可以用于任何类型的项目。

None of these solutions are specific to Avalonia, and they can be used with any type of projects.
## 运行时条件

## Runtime Conditions
.NET 6 及更高版本提供了一组在运行时获取操作系统信息的API -
[OperatingSystem](https://learn.microsoft.com/en-us/dotnet/api/system.operatingsystem)。

.NET 6 and newer provide a set of APIs to get operating system in runtime - [OperatingSystem](https://learn.microsoft.com/en-us/dotnet/api/system.operatingsystem).
这个类中常用的一些静态方法包括:

Commonly used static methods of this class are:
| Method | Description |
| 方法 | 描述 |
| --- | --- |
| IsWindows() | Indicates whether the current application is running on Windows. |
| IsLinux() | Indicates whether the current application is running on Linux. |
| IsMacOS() | Indicates whether the current application is running on macOS. |
| IsAndroid() | Indicates whether the current application is running on Android. |
| IsIOS() | Indicates whether the current application is running on iOS or MacCatalyst. |
| IsBrowser() | Indicates whether the current application is running as WASM in a browser. |
| IsOSPlatform(String) | Indicates whether the current application is running on the specified platform. |
| IsWindows() | 指示当前应用程序是否在Windows上运行。 |
| IsLinux() | 指示当前应用程序是否在Linux上运行。 |
| IsMacOS() | 指示当前应用程序是否在macOS上运行。 |
| IsAndroid() | 指示当前应用程序是否在Android上运行。 |
| IsIOS() | 指示当前应用程序是否在iOS或MacCatalyst上运行。 |
| IsBrowser() | 指示当前应用程序是否在浏览器中以WASM形式运行。 |
| IsOSPlatform(String) | 指示当前应用程序是否在指定的平台上运行。 |

These methods do not require any changes in the project structure, and can be used anywhere.
The disadvantage of using them, it is not possible to separate platform specific APIs in compile time. As otherwise it would require platform specific dependencies to be referenced in a common assembly.
这些方法不需要对项目结构进行任何更改,并且可以在任何地方使用。
缺点是无法在编译时分离平台特定的API,这样就需要在公共的程序集中引用平台特定的依赖项。

This approach is recommended for simpler scenarios, or when it's desired to keep simple project structure. In the last case,
这种方法适用于简单的场景,或者希望保持简单的项目结构。在后一种情况下

:::note
It's the only possible approach to write a conditional .NET code for Linux OS. As .NET doesn't have a special Target Framework for Linux.
这是编写针对Linux操作系统的条件.NET代码的唯一可能方法,因为.NET没有专门针对Linux的目标框架。
:::

## Conditional compilation
## 条件编译

C# specifically allows to have conditional compilation with `#if`, `#elif`, `#else`, `#endif` - [C# preprocessor directives](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives#conditional-compilation).
C# 特别地允许使用 `#if``#elif``#else``#endif` 进行条件编译 - [C# 预处理器指令](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives#conditional-compilation)

`DEBUG` compile time constant is a well known one. But it's not really useful with writing platform specific code.
Depending on the project time, C# compiler might define additional constants per each [OS specific Target Framework](https://learn.microsoft.com/en-us/dotnet/standard/frameworks#net-5-os-specific-tfms) used in the project:
`DEBUG` 是一个众所周知的编译时常量。但编写平台特定的代码时它并不是特别有用。根据项目的需要,C# 编译器可能会为每个 [操作系统特定的 Target Framework](https://learn.microsoft.com/en-us/dotnet/standard/frameworks#net-5-os-specific-tfms) 定义额外的常量:

|Target Framework | Constant |
|----|----|
| 目标框架 | 常量 |
| ---- | ---- |
| net8.0 | - |
| net8.0-windows | WINDOWS |
| net8.0-macos | MACOS |
Expand All @@ -50,28 +50,27 @@ Depending on the project time, C# compiler might define additional constants per
| net8.0-android | ANDROID |
| net8.0-tizen | TIZEN |

From this table, we can see couple of notes:
1. If project doesn't use any OS specific Target Framework, none of these constants will be defined
2. **There is no constant for LINUX**, as there is no `net8.0-linux` Target Framework as of now. Note, it might be changed in the future versions of .NET.
3. Additionally, `net8.0-browser` is only available starting with .NET 8 SDK. Other Target Frameworks are supported with .NET 6 or higher.
从上表中,我们可以注意到几点:
1. 如果项目没有使用任何特定于操作系统的目标Framework,则不会定义这些常量。
2. **没有针对 LINUX 的常量**,因为目前没有 `net8.0-linux` 的目标框架。请注意,这可能会在未来版本的 .NET 中发生变化。
3. 此外,`net8.0-browser` 仅在 .NET 8 SDK 中可用。其他目标框架支持 .NET 6 或更高版本。

:::note
Similar approach can be used to define special code compilation for .NET Framework or .NET Standard projects, if it's required. Visit Microsoft [Cross-platform targeting
](https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/cross-platform-targeting) documentation for more information.
类似的方法也可以用于定义 .NET Framework 或 .NET Standard 项目的特殊代码编译,如果需要的话。请访问 Microsoft [跨平台目标](https://learn.microsoft.com/en-us/dotnet/standard/library-guidance/cross-platform-targeting) 文档以获取更多信息。
:::

### Practical example
### 实际案例

Let's imagine, we want to use platform APIs from C# code. It can be Avalonia APIs, or Xamarin APIs, or anything else really.
First of all, expected Target Frameworks needs to be defined in the project. To keep it simple, we will have three possible target framework - "net8.0" (default), "net8.0-ios" and "net8.0-android" in `.csproj` file:
假设我们想在 C# 代码中使用平台 API。它可以是 Avalonia API、Xamarin API 或其他任何 API。
首先,需要在项目中定义预期的目标框架。为了简单起见,我们在 `.csproj` 文件中定义三个可能的目标框架 - "net8.0"(默认)、"net8.0-ios" "net8.0-android"

```xml
<PropertyGroup>
<TargetFrameworks>net8.0;net8.0-ios;net8.0-android</TargetFrameworks>
</PropertyGroup>
```

And then it's possible to create a method like this:
然后可以创建如下方法:
```csharp
public enum DeviceOrientation
{
Expand All @@ -98,29 +97,27 @@ public static DeviceOrientation GetOrientation()
```

:::note
This sample code is referenced from the Microsoft documentation: https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/invoke-platform-code?view=net-maui-8.0#conditional-compilation
此示例代码引用自Microsoft文档:https://learn.microsoft.com/en-us/dotnet/maui/platform-integration/invoke-platform-code?view=net-maui-8.0#conditional-compilation
:::

## 平台特定的项目

## Platform specific projects
类似于前面的方法,可以为每个平台创建引导项目,并保留包含主要逻辑和布局的共享项目。例如,默认的 Avalonia.Xplat模板会创建一个包含以下项目的解决方案:

Similarly to the previous approach, it is possible to create bootstrap projects per each platform, and keep shared project with main logic and layouts.
For example, default Avalonia.Xplat template creates solution with following projects:

| Project | Target Framework |
| 项目 | 目标框架 |
| --- | --- |
| Project.Shared | net8.0 |
| Project.Desktop | net8.0 |
| Project.Android | net8.0-android |
| Project.iOS | net8.0-ios |
| Project.Browser | net8.0-browser |

Desktop project combines Windows, macOS and Linux. While mobile and browser platforms have their own projects.
This is default approach for Avalonia projects. If desired, developers can split Desktop project into multiple as well.
Although, it should be kept in mind, that .NET SDK doesn't have any target framework for Linux yet, so it still would have to use generic `net8.0` target framework.
WindowsmacOS 和 Linux的桌面平台项目是统一的一个,而移动和浏览器平台则有自己的项目。
这是Avalonia项目的默认方式。如果需要,开发者也可以将桌面项目拆分为多个项目。
不过需要注意的是,.NET SDK 目前还没有针对Linux的目标框架,因此仍然需要使用通用的 `net8.0` 目标框架。

Commonly, when any platform specific code is required, a new interface is created in shared project, with different implementations per each platform.
Adapting previous sample would look like this:
通常,当需要任何平台特定的代码时,会在共享项目中创建一个新的接口,并为每个平台提供不同的实现。
之前的示例将如下所示:
```csharp title='Project.Shared IDeviceOrientation.cs'
public interface IDeviceOrientation
{
Expand Down Expand Up @@ -153,4 +150,4 @@ public class iOSDeviceOrientation : IDeviceOrientation
}
```

Each implementation then can be registered using dependency injection library of choice, or using a static registry property.
每个实现可以使用所选的依赖注入库或静态注册属性进行注册。
Original file line number Diff line number Diff line change
@@ -1,54 +1,55 @@
---
id: xaml
title: Platform-Specific XAML
title: 特定平台的XAML
---

## OnPlatform Markup Extension
## OnPlatform 标记扩展

### Overview
The OnPlatform markup extension in Avalonia allows developers to specify different values for a property based on the operating system on which the application is running. This is particularly useful for creating cross-platform applications that need to adapt their UI or behavior according to the platform.
### 概述

### Basic usage in markup extension syntax
Avalonia中的OnPlatform标记扩展(Markup Extension)允许开发人员根据应用程序运行的操作系统指定属性的不同值。这对于创建需要根据平台调整其 UI 或行为的跨平台应用程序特别有用。

You can specify values for each platform and a default value that will be used if no specific platform match is found.
### 标记扩展语法的基本用法

您可以在标记扩展语法中为每个平台指定值,并为未找到特定平台匹配的情况指定默认值:

```xml
<TextBlock Text="{OnPlatform Default='Unknown', Windows='Im Windows', macOS='Im macOS', Linux='Im Linux'}"/>
```

Alternatively, you can use constructor syntax to define the default value directly, skipping `Default` keyword. Platform-specific properties still needs to be defined.
或者,您可以使用构造函数语法直接定义默认值,跳过 `Default` 关键字。但是平台特定的属性仍需定义:

```xml
<TextBlock Text="{OnPlatform 'Hello World', Android='Im Android'}"/>
```

You can use this markup extension with any other type, not only strings:
您可以将此标记扩展搭配任何其他类型使用,而不仅仅是字符串:

```xml
<Border Height="{OnPlatform 10, Windows=50.5}"/>
```

### Specifying Type Arguments
### 指定类型参数

You can use custom TypeArguments to explicitly specify the type for the values.
您可以使用自定义的TypeArguments 显式指定值的类型:

```xml
<TextBlock Tag="{OnPlatform '0, 0, 0, 0', Windows='10, 10, 10, 10', x:TypeArguments=Thickness}"/>
```

In this sample above, `Tag` property has type of `object`, so compiler doesn't have enough information to parse input strings. Without specifying TypeArguments, property will have value of `string` on all platforms. But since we have `TypeArguments` here, compiler will parse them as `Thickness` values.
在上面的示例中,`Tag` 属性的类型为 `object`,因此编译器没有足够的信息来解析输入字符串。如果不指定 TypeArguments,属性在所有平台上都将具有 `string` 类型。但由于我们有 `TypeArguments`,编译器将解析它们为 `Thickness` 值。

### Nested Markup Extensions
### 嵌套标记扩展

The OnPlatform extension supports nesting other markup extensions within it.
OnPlatform 扩展支持在其内部嵌套其他标记扩展:

```xml
<Border Background="{OnPlatform Default={StaticResource DefaultBrush}, Windows={StaticResource WindowsBrush}}"/>
```

### XML Syntax
### XML 语法

OnPlatform can also be used in XML syntax for defining property values.
OnPlatform 也可以在 XML 语法中用于定义属性值:

```xml
<StackPanel>
Expand All @@ -58,16 +59,16 @@ OnPlatform can also be used in XML syntax for defining property values.
</OnPlatform.Default>
<OnPlatform.iOS>
<ToggleSwitch Content="Hello iOS" />
</OnPlatform.Windows>
</OnPlatform.iOS>
</OnPlatform>
</StackPanel>
```

Note, in this sample, `OnPlatform` is a child of `StackPanel`. But in runtime only single actual control will be created (`ToggleButton` or `ToggleSwitch`) and added to the StackPanel.
注意,在此示例中,`OnPlatform` `StackPanel` 的子元素。但在运行时,只会创建一个实际的控件(`ToggleButton` `ToggleSwitch`)并添加到 `StackPanel` 中。

### Complex Property Setters
### 复杂属性设置器

Similarly to the previous sample, OnPlatform can be part of complex property setters within a ResourceDictionary or other dictionaries or collections.
类似于前面的示例,OnPlatform 可以作为复杂属性设置器的一部分,用于资源字典或其他字典或集合中:

```xml
<ResourceDictionary>
Expand All @@ -77,22 +78,21 @@ Similarly to the previous sample, OnPlatform can be part of complex property set
</OnPlatform.Default>
<OnPlatform.iOS>
<SolidColorBrush Color="Yellow" />
</OnPlatform.Windows>
</OnPlatform.iOS>
</OnPlatform>
</ResourceDictionary>
```

### XML Combining Syntax
### XML 组合语法

To avoid branches duplication, it is possible to define multiple platforms in a single branch.
Another useful example would be including platform specific styles:
为了避免分支重复,可以在单个分支中定义多个平台。另一个有用的示例是包含平台特定的样式:

```xml
<Application.Styles>
<!-- Always included -->
<!-- 始终包含 -->
<FluentTheme />

<!-- Only one branch is executed in runtime -->
<!-- 运行时只执行一个分支 -->
<OnPlatform>
<!-- if (Android || iOS) -->
<On Options="Android, iOS">
Expand All @@ -106,17 +106,15 @@ Another useful example would be including platform specific styles:
</Application.Styles>
```

### Additional details

`OnPlatform` markup extension work in a similar way how `switch-case` works in C# code.
Compiler will generate branches for all possible values, but only single branch will be executed in runtime depending on the condition.
### 其他细节

It's also useful to remember, that if application is build with specific [Runtime Identifier](https://learn.microsoft.com/en-us/dotnet/core/rid-catalog) and with [Trimming Enabled](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options), `OnPlatform` extension will have its branches trimmed only to these that are possible. For example, if `OnPlatform` had branches for `Windows` and `macOS`, but was built for `Windows` only, other branches will be removed. Which also reduces application size.
OnPlatform 标记扩展的工作方式类似于 C# 代码中的 switch-case。编译器将为所有可能的值生成分支,但在运行时仅根据条件执行一个分支。

还值得注意的是,如果应用程序是使用特定的 [运行时标识符](https://learn.microsoft.com/en-us/dotnet/core/rid-catalog) 并且启用了 [Trim](https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options),OnPlatform 扩展将只保留可能的分支。例如,如果OnPlatform有Windows和macOS的分支,但仅构建为 Windows,其他分支将被移除,这也减少了应用程序的大小。

## OnFormFactor Markup Extension
## OnFormFactor 标记扩展

The `OnFormFactor` markup extension functions similarly to the `OnPlatform` and has the same general syntax. The main difference is that it allows defining values not per platform, but per device form factor, such as Desktop and Mobile.
`OnFormFactor` 标记扩展的功能类似于 `OnPlatform`,并且具有相同的通用语法。主要区别在于,它允许根据设备的外形因素(如桌面和移动设备)而不是平台来定义值:

```xml
<UserControl xmlns="https://github.com/avaloniaui"
Expand All @@ -125,5 +123,4 @@ The `OnFormFactor` markup extension functions similarly to the `OnPlatform` and
</UserControl>
```

`OnFormFactor` doesn't have any compile-time trimming kinds of optimizations, as form factor cannot be known in compile time.
None of these markup extensions are dynamic, which means, once value was set, it will not be changed.
`OnFormFactor` 没有编译时的修剪优化,因为外形因素在编译时无法确定。这些标记扩展都不是动态的;一旦设置了值,就不会再改变。
Loading