استفاده از «پیکربندی از راه دور» در محیط‌های سرور

Firebase Remote Config از پیکربندی سمت سرور بااستفاده از «کیت‌های توسعه نرم‌افزار Firebase Admin» برای Node.js (نسخه ۱۲٫۱٫۰ به بالا)، Python (نسخه ۶٫۷٫۰ به بالا)، Java (نسخه ۹٫۷٫۰ به بالا)، و Go (نسخه ۴٫۱۷٫۰ به بالا) پشتیبانی می‌کند.

این قابلیت به شما امکان می‌دهد رفتار و پیکربندی برنامه‌های سمت سرور را بااستفاده از Remote Config به‌طور پویا مدیریت کنید. این شامل پیاده‌سازی‌های بدون سرور مانند Cloud Functions for Firebase و سرویس‌های کانتینری در Cloud Run می‌شود.

برخلاف کیت‌های توسعه نرم‌افزار کارخواه Firebase که پیکربندی مختص کارخواه را که از الگوی Remote Config مشتق شده است واکشی می‌کنند، کیت توسعه نرم‌افزار Remote Config سمت سرور الگوی Remote Config کامل را از Firebase بارگیری یا واکشی می‌کند. سپس سرور شما می‌تواند الگو را با هر درخواست ورودی ارزیابی کند و از منطق خودش برای ارائه پاسخ سفارشی با تأخیر بسیار کم استفاده کند. می‌توانید از شرایط برای کنترل و سفارشی‌سازی پاسخ‌ها براساس درصدهای تصادفی و مشخصه‌های مشتری تعریف‌شده در سیگنال‌های سفارشی استفاده کنید.

با Remote Config سمت سرور، می‌توانید:

  • پارامترهای پیکربندی را برای برنامه‌هایی که در سرور شما اجرا می‌شوند یا ازطریق آن قابل‌دسترسی هستند تعریف کنید تا امکان استفاده از مواردی مانند پیکربندی از راه دور پارامترها و پیام‌واره‌های مدل هوش مصنوعی و سایر ادغام‌ها فراهم شود و اطمینان حاصل شود که کلیدهای API شما ایمن می‌مانند.
  • پارامترها را به‌طور پویا در پاسخ به تغییرات محیط یا تغییرات دیگر برنامه، مانند به‌روزرسانی پارامترهای مدل زبانی بزرگ و نقاط پایانی مدل، تنظیم کنید.
  • با به‌روزرسانی ازراه‌دور میاناهای برنامه‌سازی کاربردی که سرورتان فراخوانی می‌کند، هزینه‌ها را کنترل کنید.
  • پیکربندی‌های سفارشی را به‌طور هم‌زمان برای کارخواه‌هایی که به سرور شما دسترسی دارند تولید کنید.
  • ثبت کنید کدام مشتریان مقدار پارامتر را دریافت کرده‌اند و از آن در Cloud Functions for Firebase به‌عنوان بخشی از سیستم درستی‌سنجی استحقاق استفاده کنید.

می‌توانید Remote Config سمت سرور را در Cloud Run، Cloud Functions for Firebase، یا محیط‌های سرور خودمیزبان پیاده‌سازی کنید.

قبل از شروع

دستورالعمل‌های موجود در افزودن Firebase Admin SDK به سرور را دنبال کنید تا پروژه Firebase ایجاد کنید، حساب سرویس راه‌اندازی کنید، و Firebase Admin SDK را به سرور خود اضافه کنید. مطمئن شوید که از نسخه پشتیبانی‌شده Admin SDK برای پلاتفرم خود استفاده می‌کنید:

  • Node.js: Firebase Admin Node.js SDK v12.1.0+
  • Python: Firebase Admin Python SDK v6.7.0+‎
  • Java: Firebase Admin Java SDK v9.7.0+‎
  • Go: Firebase Admin Go SDK v4.17.0+

مرحله ۱: مقداردهی اولیه «کیت توسعه نرم‌افزار Firebase Admin» و صدور مجوز برای درخواست‌های API

وقتی Admin SDK را بدون پارامتر مقداردهی اولیه می‌کنید، SDK از اعتبارنامه‌های پیش‌فرض برنامه Google استفاده می‌کند و گزینه‌ها را از متغیر محیطی GOOGLE_APPLICATION_CREDENTIALS می‌خواند. کیت توسعه نرم‌افزار را مقداردهی اولیه کنید و Remote Config را برای پلاتفرم خودتان پیکربندی کنید:

Node.js

initializeApp و getRemoteConfig را وارد کنید، سپس نمونه برنامه Firebase خود را مقداردهی اولیه کنید:

import { initializeApp } from "firebase-admin/app";
import { getRemoteConfig } from "firebase-admin/remote-config";

// Initialize Firebase
const firebaseApp = initializeApp();

پایتون

firebase_admin را وارد کنید (همراه با asyncio و json برای بار کردن ناهمگام الگو و تجزیه JSON)، سپس برنامه را مقداردهی اولیه کنید:

import firebase_admin
import asyncio
import json

firebase_admin.initialize_app()

جاوا

«کیت توسعه نرم‌افزار Firebase Admin» را بااستفاده از FirebaseOptions و اعتبارنامه‌های حساب سرویس خود مقداردهی اولیه کنید:

// Initialize the Firebase Admin SDK
FirebaseOptions options = new FirebaseOptions.Builder()
    .setCredentials(GoogleCredentials.fromStream(serviceAccount))
    .build();
FirebaseApp.initializeApp(options);

رفتن

برنامه Firebase را مقداردهی اولیه کنید و یک نمونه کارخواه RemoteConfig ایجاد کنید:

ctx := context.Background()

// Initialize Firebase
app, err := firebase.NewApp(ctx, nil)
if err != nil {
    log.Fatalln("Error initializing app:", err)
}

remoteConfig, err := app.RemoteConfig(ctx)
if err != nil {
    log.Fatalln("Error initializing remote config client:", err)
}

مرحله ۲: شناسایی مقادیر پارامتر پیش‌فرض برای برنامه سرور

متغیرهای موجود در برنامه‌تان را که می‌خواهید به‌طور پویا با Remote Config به‌روزرسانی شوند شناسایی کنید. سپس، درنظر بگیرید که کدام متغیرها باید به‌طور پیش‌فرض در برنامه‌تان تنظیم شوند و مقادیر پیش‌فرض آن‌ها چه باید باشد. این کار تضمین می‌کند که برنامه شما حتی اگر اتصالش به سرور زیرینه Remote Config قطع شود، با موفقیت اجرا شود.

برای مثال، اگر درحال نوشتن برنامه سروری هستید که تابع هوش مصنوعی زایا را مدیریت می‌کند، می‌توانید نام مدل پیش‌فرض، مقدمه پیام‌واره، و پیکربندی هوش مصنوعی زایا را به‌صورت زیر تنظیم کنید:

نام پارامتر شرح تایپ کردن مقدار پیش‌فرض
model_name نام میانای برنامه‌سازی کاربردی مدل تار gemini-3.8-flash
preamble_prompt پیام‌واره‌ای که باید به ابتدای پُرسمان کاربر اضافه شود تار I'm a developer who wants to learn about Firebase and you are a helpful assistant who knows everything there is to know about Firebase!
generation_config پارامترهایی که باید به مدل ارسال شود JSON {"stopSequences": ["I hope this helps"], "maxOutputTokens": 512}

مرحله ۳: پیکربندی برنامه سرور

پس‌از تعیین پارامترهایی که می‌خواهید با Remote Config استفاده کنید، برنامه‌تان را برای تنظیم مقادیر پیش‌فرض، واکشی الگوی Remote Config مختص سرور، و ارزیابی مقادیر آن پیکربندی کنید.

  1. به الگوی سرور Remote Config دسترسی پیدا کنید و آن را بار کنید.

    Node.js

    الگوی سرور را بااستفاده از initServerTemplate() مقداردهی اولیه کنید و load() را فراخوانی کنید تا الگو را از زیرینه واکشی کنید:

    // Initialize server-side Remote Config
    const rc = getRemoteConfig(firebaseApp);
    const template = rc.initServerTemplate();
    
    // Load Remote Config
    await template.load();
    

    اگر از Node.js در Cloud Functions for Firebase استفاده می‌کنید، می‌توانید از تابع ناهمگام getServerTemplate() برای مقداردهی اولیه و بار کردن الگو در یک مرحله استفاده کنید:

    // Initialize server-side Remote Config
    const rc = getRemoteConfig(firebaseApp);
    const template = await rc.getServerTemplate();
    

    پایتون

    الگوی سرور را بااستفاده از init_server_template() مقداردهی اولیه کنید و load() را فراخوانی کنید تا الگو را از زیرینه واکشی کنید:

    from firebase_admin import remote_config
    
    # Initialize server-side Remote Config
    template = remote_config.init_server_template()
    
    # Load the template from the backend
    asyncio.run(template.load())
    

    یا اگر از Python با Cloud Functions for Firebase استفاده می‌کنید، می‌توانید از تابع ناهمگام get_server_template() برای مقداردهی اولیه و بار کردن الگو در یک مرحله استفاده کنید:

    # Initialize server-side Remote Config
    template = await remote_config.get_server_template()
    

    جاوا

    مقداردهی اولیه کارخواه Remote Config سمت سرور بااستفاده از FirebaseRemoteConfig.getInstance():

    // Initialize server-side Remote Config client
    FirebaseRemoteConfig rc = FirebaseRemoteConfig.getInstance();
    

    یا اگر از Java با Cloud Functions for Firebase استفاده می‌کنید، می‌توانید از getServerTemplate() برای مقداردهی اولیه و بار کردن الگو در یک مرحله استفاده کنید:

    ServerTemplate template = rc.getServerTemplate();
    

    رفتن

    الگوی سرور را بااستفاده از InitServerTemplate() مقداردهی اولیه کنید و Load() را فراخوانی کنید تا الگو را از زیرینه واکشی کنید:

    // Initialize server-side Remote Config
    defaultConfig := make(map[string]any)
    templateDataJSON := ""
    template, err := remoteConfig.InitServerTemplate(defaultConfig, templateDataJSON)
    if err != nil {
        log.Fatalln("Error initializing server template:", err)
    }
    
    // Load Remote Config
    err = template.Load(ctx)
    if err != nil {
        log.Fatalln("Error fetching server template:", err)
    }
    

    روش دیگری که می‌توانید الگو را راه‌اندازی کنید استفاده از تابع GetServerTemplate برای بازیابی الگوی سرور موردنیاز است. می‌توانید این الگو را به قالب JSON تبدیل کنید که می‌تواند به‌صورت محلی ذخیره شود، و سپس این الگوی JSON را بااستفاده از تابع InitServerTemplate مقداردهی اولیه کنید.

  2. برای اطمینان از اینکه برنامه‌تان حتی درصورت قطع اتصال به سرور زیرینه Remote Config با موفقیت اجرا می‌شود، مقادیر پیش‌فرضی برای هر پارامتر در برنامه‌تان اضافه کنید.

    Node.js

    شیء defaultConfig را به تابع الگوی initServerTemplate یا getServerTemplate اضافه کنید:

    const template = rc.initServerTemplate({
      defaultConfig: {
        model_name: "gemini-3.8-flash",
        generation_config: '{"stopSequences": [], "maxOutputTokens": 512}',
        preamble_prompt: "I'm a developer who wants to learn about Firebase and you are a helpful assistant who knows everything there is to know about Firebase!"
      },
    });
    
    // Load Remote Config
    await template.load();
    

    پایتون

    یک واژه‌نامه default_config را در تابع الگوی init_server_template یا get_server_template خود اضافه کنید:

    template = remote_config.init_server_template({
      'default_config': {
        'model_name': "gemini-3.8-flash",
        'generation_config': '{"stopSequences": [], "maxOutputTokens": 512}',
        'preamble_prompt': "I'm a developer who wants to learn about Firebase and you are a helpful assistant who knows everything there is to know about Firebase!"
      },
    })
    
    # Load Remote Config
    asyncio.run(template.load())
    

    روش دیگری که می‌توانید برای مقداردهی اولیه الگو استفاده کنید، استفاده از تابع get_server_template برای بازیابی الگوی سرور موردنیاز است. می‌توانید این الگو را بااستفاده از تابع template.to_json به قالب JSON تبدیل کنید. این الگوی JSON را می‌توان به‌صورت محلی ذخیره کرد و می‌توانید متعاقباً این الگوی JSON را بااستفاده از تابع init_server_template مقداردهی اولیه کنید.

    جاوا

    بااستفاده از KeysAndValues، شیء defaultConfig را در تابع getServerTemplate اضافه کنید:

    // Initialize default config using KeysAndValues
    KeysAndValues defaultConfig = new KeysAndValues.Builder()
                                      .put("rc_param_1", "default value 1")
                                      .put("rc_param_2", "default value 2")
                                      .build();
    ServerTemplate template = rc.getServerTemplate(defaultConfig);
    

    یا می‌توانید هنگام مقداردهی اولیه Remote Config، یک الگوی ذخیره‌شده پیش‌فرض را ارسال کنید که حتی درصورت قطع اتصال به سرور Remote Config قابل‌استفاده است:

    String templateDataJSON = "{}"; // add your default template as JSON
    ServerTemplate template = rc.serverTemplateBuilder()
                        .defaultConfig(defaultConfig)
                        .cachedTemplate(templateDataJSON)
                        .build();
    

    رفتن

    نقشه defaultConfig را در تابع الگوی InitServerTemplate یا GetServerTemplate خود اضافه کنید:

    // Initialize server-side Remote Config
    defaultConfig := make(map[string]any)
    defaultConfig["model_name"] = "gemini-3.8-flash"
    
    // Assume the type generationConfig has been defined
    defaultConfig["generation_config"] = &generationConfig{
        StopSequences:   []string{"I hope this helps"},
        MaxOutputTokens: 512,
    }
    
    defaultConfig["preamble_prompt"] = "I'm a developer who wants to learn about Firebase and you are a helpful assistant who knows everything there is to know about Firebase!"
    
    templateDataJSON := ""
    template, err := remoteConfig.InitServerTemplate(defaultConfig, templateDataJSON)
    if err != nil {
        log.Fatalln("Error initializing server template:", err)
    }
    
    // Load Remote Config
    err = template.Load(ctx)
    if err != nil {
        log.Fatalln("Error fetching server template:", err)
    }
    
  3. پس‌از بار شدن الگو، الگو را ارزیابی کنید تا پارامترها و مقادیر را از الگو وارد کنید:

    Node.js

    از template.evaluate() استفاده کنید:

    // Add template parameters to config
    const config = template.evaluate();
    

    پایتون

    از template.evaluate() استفاده کنید:

    # Add template parameters to config
    config = template.evaluate()
    

    جاوا

    از template.evaluate() استفاده کنید:

    // Add template parameters to config
    ServerConfig config = template.evaluate();
    

    رفتن

    وقتی هیچ شرطی اعمال نشده است، از template.Evaluate() با بافت ارزیابی خالی استفاده کنید:

    // An empty evaluation context means no conditions are applied.
    evaluationContext := make(map[string]any)
    config, err := template.Evaluate(evaluationContext)
    if err != nil {
        log.Fatalln("Error evaluating template:", err)
    }
    
  4. اختیاری: اگر در الگوی Remote Config شرایطی تنظیم کرده‌اید، مقادیر بافت موردنظرتان را تعریف و ارائه کنید:

    • اگر از شرایط درصدی استفاده می‌کنید، شناسه تصادفی‌سازی (randomizationId، randomization_id، یا randomizationID) را که می‌خواهید برای ارزیابی شرایطتان استفاده کنید در تابع ارزیابی الگو اضافه کنید.
    • اگر از سیگنال‌های سفارشی استفاده می‌کنید، مشخصه‌ها و مقادیر آن‌ها را تعریف کنید. سیگنال‌های سفارشی با Firebase Admin Node.js SDK v12.5.0+‎،‏ Python SDK v6.7.0+‎،‏ Java SDK v9.7.0+‎، و Go SDK v4.17.0+‎ دردسترس است.

    برای مثال، می‌توانید Firebase شناسه نصب یا شناسه کاربر را به‌عنوان شناسه تصادفی‌سازی تنظیم کنید تا مطمئن شوید هر کاربری که با سرور شما تماس می‌گیرد به گروه تصادفی مناسب اضافه می‌شود، version به‌عنوان سیگنال سفارشی برای هدف‌یابی نسخه‌های کارخواه خاص، و platform به‌عنوان سیگنال سفارشی برای هدف‌یابی پلاتفرم‌های کارخواه.

    برای اطلاعات بیشتر درباره شرایط، به انواع قانون شرط مراجعه کنید.

    Node.js

    یک شیء بافت ارزیابی حاوی randomizationId و هرگونه سیگنال سفارشی را به template.evaluate() ارسال کنید:

    // Add template parameters to `config`. Evaluates the
    // template and returns the parameter value assigned to
    // the group assigned to the {randomizationId} and version.
    const config = template.evaluate({
      randomizationId: "2ac93c28-c459-4760-963d-a3974ec26c04",
      version: "1.0",
      platform: "Android"
    });
    

    پایتون

    واژه‌نامه‌ای حاوی randomization_id و هرگونه سیگنال سفارشی را به template.evaluate() ارسال کنید:

    # Add template parameters to `config`. Evaluates the
    # template and returns the parameter value assigned to
    # the group assigned to the {randomization_id} and version.
    config = template.evaluate({
      'randomization_id': "2ac93c28-c459-4760-963d-a3974ec26c04",
      'version': "1.0",
      'platform': "Android"
    })
    

    جاوا

    یک زمینه KeysAndValues حاوی randomizationId و هرگونه سیگنال سفارشی ایجاد کنید و آن را به template.evaluate() ارسال کنید:

    // Add custom signals and randomizationId
    KeysAndValues context = new KeysAndValues.Builder()
                                    .put("custom_signal_key", "99")
                                    .put("randomizationId", "2ac93c28")
                                    .build();
    
    // Evaluate the template with signals
    ServerConfig config = template.evaluate(context);
    

    رفتن

    یک نقشه بافتار ارزیابی حاوی randomizationID و هرگونه سیگنال سفارشی را به template.Evaluate() ارسال کنید:

    // Add template parameters to `config`. Evaluates the
    // template and returns the parameter value assigned to
    // the group assigned to the {randomizationID}, version, and platform.
    evaluationContext := make(map[string]any)
    evaluationContext["randomizationID"] = "2ac93c28-c459-4760-963d-a3974ec26c04"
    evaluationContext["version"] = "1.0"
    evaluationContext["platform"] = "Android"
    
    config, err := template.Evaluate(evaluationContext)
    if err != nil {
        log.Fatalln("Error evaluating template:", err)
    }
    
  5. سپس، مقادیر پارامتر موردنیازتان را از شیء پیکربندی ارزیابی‌شده استخراج کنید. از روش‌های گیرنده برای تبدیل مقادیر از Remote Config به قالب موردانتظار استفاده کنید.

    برای مثال، اگر Agent Platform را در سرورتان پیاده‌سازی می‌کنید و می‌خواهید مدل و پارامترهای مدل را تغییر دهید، می‌توانید پارامترهای model_name و generation_config را پیکربندی کنید. در اینجا روش‌های گیرنده پشتیبانی‌شده و نمونه‌ای از نحوه دسترسی به مقادیر Remote Config برای هر پلاتفرم آورده شده است:

    Node.js

    روش‌های گیرنده پشتیبانی‌شده:

    • بولی: getBoolean
    • شیء: getValue
    • شماره: getNumber
    • رشته: getString

    // Replace defaults with values from Remote Config.
    const generationConfig =
      JSON.parse(
        config.getString('generation_config'));
    
    const is_ai_enabled = config.getBoolean('is_ai_enabled');
    
    const model = config.getString('model_name');
    
    // Generates a prompt comprised of the Remote Config
    // parameter and prepends it to the user prompt
    const prompt = `${config.getString('preamble_prompt')} ${req.query.prompt}`;
    

    پایتون

    روش‌های گیرنده پشتیبانی‌شده:

    • بولی: get_bool
    • عدد صحیح: get_int
    • شناور: get_float
    • رشته: get_string
    • منبع مقدار: get_value_source

    # Replace defaults with values from Remote Config.
    generation_config = json.loads(config.get_string('generation_config'))
    is_ai_enabled = config.get_bool('is_ai_enabled')
    model = config.get_string('model_name')
    
    # Generates a prompt comprised of the Remote Config
    # parameter and prepends it to the user prompt.
    prompt = f"{config.get_string('preamble_prompt')}{req.args.get('prompt')}"
    

    جاوا

    روش‌های گیرنده پشتیبانی‌شده:

    • بولی: getBoolean
    • رشته: getString
    • دوبرابر: getDouble
    • طولانی: getLong
    • منبع مقدار: getValueSource

    // Get the model name
    String modelName = config.getString("model_name");
    // Get the origin of value assigned to param
    ValueSource modelNameSource = config.getValueSource("model_name");
    

    روش getValueSource یک ValueSource برمی‌گرداند که نشان می‌دهد منبع مقدار پارامتر STATIC، REMOTE، یا DEFAULT است.

    رفتن

    روش‌های گیرنده پشتیبانی‌شده:

    • بولی: GetBoolean
    • عدد صحیح: GetInt
    • شناور: GetFloat
    • رشته: GetString
    • منبع مقدار: GetValueSource

    // Replace defaults with values from Remote Config.
    
    // Assume the type generationConfig has been defined
    var genConfig generationConfig
    err = json.Unmarshal([]byte(config.GetString("generation_config")), &genConfig)
    if err != nil {
        log.Fatalln("Error unmarshaling generation config:", err)
    }
    model := config.GetString("model_name")
    
    // Parameter created on the console
    isAIEnabled := config.GetBoolean("is_ai_enabled")
    
    // Generates a prompt comprised of the Remote Config
    // parameter and prepends it to the user prompt (assume it is extracted from the request body)
    userPrompt := "What is Remote Config?"
    prompt := fmt.Sprintf("%s %s", config.GetString("preamble_prompt"), userPrompt)
    
  6. اگر سرورتان طولانی‌مدت اجرا می‌شود، برخلاف محیط بدون سرور، به‌طور دوره‌ای الگو را مجدداً بار کنید (برای مثال، بااستفاده از setInterval در Node.js یا java.util.Timer در Java) تا مطمئن شوید که به‌روزترین الگو را از سرور Remote Config واکشی می‌کنید.

مرحله ۴: تنظیم مقادیر پارامترهای خاص سرور در Remote Config

سپس، الگوی Remote Config سرور ایجاد کنید و پارامترها و مقادیر را برای استفاده در برنامه‌تان پیکربندی کنید.

در اینجا نحوه ایجاد الگوی Remote Config مختص سرور آورده شده است:

  1. در کنسول Firebase، به صفحه DevOps و تعامل > پیکربندی از راه دور > پارامترها بروید.

  2. از انتخابگر کارخواه/سرور در بالای صفحه، سرور را انتخاب کنید.

  3. Remote Config پارامتر با نام‌ها و انواع داده یکسان با پارامترهایی که در برنامه‌تان تعریف کرده‌اید تعریف کنید و مقادیر را ارائه دهید. این مقادیر پیکربندی پیش‌فرضی (defaultConfig یا default_config) را که در پیکربندی برنامه سرور تنظیم کرده‌اید هنگام واکشی و ارزیابی الگو و اختصاص دادن این مقادیر به متغیرهایتان لغو می‌کند.

  4. به‌صورت اختیاری، شرایطی را تنظیم کنید تا مقادیر به‌طور مداوم بر نمونه‌ای تصادفی از نمونه‌ها یا نشانه‌های سفارشی که تعریف می‌کنید اعمال شود. برای اطلاعات بیشتر درباره شرایط، به انواع قانون شرط مراجعه کنید.

  5. وقتی افزودن پارامترها تمام شد، روی انتشار تغییرات کلیک کنید.

  6. تغییرات را مرور کنید و دوباره روی انتشار تغییرات کلیک کنید.

مرحله ۵: استقرار با Cloud Functions for Firebase یا Cloud Run

اگر برنامه سرور شما سبک و رویدادمحور است، باید استقرار کدتان را بااستفاده از Cloud Functions for Firebase درنظر بگیرید. برای مثال، فرض کنید برنامه‌ای دارید که شامل گفتگوی شخصیت‌ها است که توسط یک میانای برنامه‌سازی کاربردی هوش مصنوعی زایا (مثلاً Google AI یا Agent Platform) پشتیبانی می‌شود. در این حالت، می‌توانید منطق ارائه‌دهنده LLM خود را در تابعی میزبانی کنید که برنامه‌تان به‌صورت درخواستی فراخوانی می‌کند.

اگر درحال ساختن برنامه وب با رندر سرور هستید، App Hosting از چارچوب‌های وب محبوب پشتیبانی می‌کند.

درغیراین‌صورت، می‌توانید Cloud Run را درنظر بگیرید. برای استقرار برنامه سرور با Cloud Run، راهنمای شروع سریع زبان خود را دنبال کنید:

مراحل بعدی