-
-
Notifications
You must be signed in to change notification settings - Fork 974
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update: translate doc french (#3194)
Hi @rrousselGit, * This PR enhances the French documentation by incorporating additional translations from the latest English documentation. * The focus is on the 'cookbook' section.
- Loading branch information
Showing
10 changed files
with
518 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
website/i18n/fr/docusaurus-plugin-content-docs/current/cookbooks/refresh.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
--- | ||
title: Pull-to-refresh / Retry-on-error | ||
--- | ||
|
||
import Tabs from "@theme/Tabs"; | ||
import TabItem from "@theme/TabItem"; | ||
|
||
Dans ce guide, nous verrons comment les Providers peuvent être utilisés pour mettre | ||
en œuvre facilement une fonction de "pull-to-refresh" ou de "retry-on-error" | ||
(tentative de réessai en cas d'erreur). |
133 changes: 133 additions & 0 deletions
133
.../i18n/fr/docusaurus-plugin-content-docs/current/cookbooks/search_as_we_type.mdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
--- | ||
titre : Recherche au fur et à mesure de la frappe | ||
--- | ||
Un exemple concret pourrait être l'utilisation de `FutureProvider` pour implémenter une barre de recherche. | ||
|
||
## Exemple d'utilisation : Barre de recherche "Search as we type" (recherche au fur et à mesure de la frappe) | ||
|
||
La mise en œuvre d'une "recherche au fil de la frappe" peut sembler décourageante au début si l'on utilise des moyens conventionnels. | ||
Il y a beaucoup d'éléments en jeu, tels que | ||
|
||
- le traitement des erreurs. | ||
- le débouclage (debouncing) de l'entrée de l'utilisateur afin d'éviter de faire des demandes de réseau à chaque frappe. | ||
- l'annulation des demandes de réseau en attente lorsque le champ de recherche change. | ||
|
||
Mais la combinaison de `FutureProvider` et de la puissance de [ref.watch] peut considérablement simplifier cette tâche. | ||
|
||
Un schéma courant pour effectuer des requêtes asynchrones est de la diviser en plusieurs providers : | ||
|
||
- un [StateNotifierProvider] ou `StateProvider` pour les paramètres de votre requête (ou alternativement utiliser [family]) | ||
- un `FutureProvider`, qui effectuera la requête en lisant les paramètres des autres providers/[family]. | ||
|
||
La première étape consiste à stocker l'entrée de l'utilisateur quelque part. Pour cet exemple, nous utiliserons `StateProvider` (puisque l'état de la recherche n'est qu'une simple `chaîne`) : | ||
|
||
```dart | ||
final searchInputProvider = StateProvider<String>((ref) => ''); | ||
``` | ||
|
||
Nous pouvons ensuite connecter ce provider à un [TextField] en faisant : | ||
|
||
```dart | ||
Consumer( | ||
builder: (context, ref, child) { | ||
return TextField( | ||
onChanged: (value) => ref.read(searchInputProvider.notifier).state = value, | ||
); | ||
}, | ||
) | ||
``` | ||
|
||
Ensuite, nous pouvons créer notre `FutureProvider` qui s'occupera de la requête : | ||
|
||
```dart | ||
final searchProvider = FutureProvider< | ||
<!-- | ||
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file | ||
// for details. All rights reserved. Use of this source code is governed by a | ||
// BSD-style license that can be found in the LICENSE file. | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:http/http.dart' as http; | ||
import 'dart:convert'; | ||
final searchFieldProvider = StateProvider<String>((ref) => ''); | ||
final questionsProvider = FutureProvider<List>((ref) async { | ||
final client = http.Client(); | ||
ref.onDispose(client.close); | ||
final search = ref.watch(searchFieldProvider); | ||
Uri uri; | ||
if (search.isEmpty) { | ||
uri = Uri.parse( | ||
'https://api.stackexchange.com/2.3/questions?order=desc&sort=activity&site=stackoverflow', | ||
); | ||
} else { | ||
final encodedQuery = Uri.encodeComponent(search); | ||
uri = Uri.parse( | ||
'https://api.stackexchange.com/2.3/search?order=desc&sort=activity&intitle=$encodedQuery&site=stackoverflow', | ||
); | ||
} | ||
final response = await client.get(uri); | ||
final questions = jsonDecode(response.body); | ||
return questions['items'].map((question) => question['title']).toList(); | ||
}); | ||
void main() => runApp(const ProviderScope(child: MyApp())); | ||
class MyApp extends StatelessWidget { | ||
const MyApp({Key? key}) : super(key: key); | ||
@override | ||
Widget build(BuildContext context) { | ||
return const MaterialApp(home: MyHomePage()); | ||
} | ||
} | ||
class MyHomePage extends ConsumerWidget { | ||
const MyHomePage({Key? key}) : super(key: key); | ||
@override | ||
Widget build(BuildContext context, WidgetRef ref) { | ||
final questions = ref.watch(questionsProvider); | ||
return Scaffold( | ||
appBar: AppBar(title: const Text('Questions')), | ||
body: Column( | ||
children: [ | ||
TextField( | ||
onChanged: (value) => | ||
ref.read(searchFieldProvider.notifier).state = value, | ||
), | ||
Expanded( | ||
child: questions.when( | ||
loading: () => const Center(child: CircularProgressIndicator()), | ||
error: (error, stack) => Center(child: Text('Error $error')), | ||
data: (questions) { | ||
return ListView.builder( | ||
itemCount: questions.length, | ||
itemBuilder: (context, index) { | ||
final question = questions[index]; | ||
return ListTile( | ||
title: Text( | ||
question.toString(), | ||
), | ||
); | ||
}, | ||
); | ||
}, | ||
), | ||
), | ||
], | ||
), | ||
); | ||
} | ||
} | ||
``` |
51 changes: 51 additions & 0 deletions
51
website/i18n/fr/docusaurus-plugin-content-docs/current/cookbooks/testing_dart.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
class FakeRepository {} | ||
|
||
final repositoryProvider = Provider((ref) => FakeRepository()); | ||
|
||
abstract class Todo { | ||
String get id; | ||
String get label; | ||
bool get completed; | ||
} | ||
|
||
final todoListProvider = FutureProvider<List<Todo>>((ref) => []); | ||
|
||
void main() { | ||
/* SNIPPET START */ | ||
|
||
test('override repositoryProvider', () async { | ||
final container = ProviderContainer( | ||
overrides: [ | ||
// Surcharge le comportement de repositoryProvider pour qu'il renvoie | ||
// FakeRepository au lieu de Repository. | ||
/* highlight-start */ | ||
repositoryProvider.overrideWithValue(FakeRepository()) | ||
/* highlight-end */ | ||
// Il n'est pas nécessaire de surcharger `todoListProvider`, | ||
// il utilisera automatiquement le repositoryProvider surchargé. | ||
], | ||
); | ||
|
||
// La première lecture si l'état est en cours de chargement | ||
expect( | ||
container.read(todoListProvider), | ||
const AsyncValue<List<Todo>>.loading(), | ||
); | ||
|
||
/// Attendre la fin de la demande (la requete) | ||
await container.read(todoListProvider.future); | ||
|
||
// Expose les données recherchées | ||
expect(container.read(todoListProvider).value, [ | ||
isA<Todo>() | ||
.having((s) => s.id, 'id', '42') | ||
.having((s) => s.label, 'label', 'Hello world') | ||
.having((s) => s.completed, 'completed', false), | ||
]); | ||
}); | ||
|
||
/* SNIPPET END */ | ||
} |
39 changes: 39 additions & 0 deletions
39
website/i18n/fr/docusaurus-plugin-content-docs/current/cookbooks/testing_flutter.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
class MyApp extends StatelessWidget { | ||
const MyApp({super.key}); | ||
|
||
@override | ||
Widget build(BuildContext context) { | ||
return Container(); | ||
} | ||
} | ||
|
||
final repositoryProvider = Provider((ref) => FakeRepository()); | ||
|
||
class FakeRepository {} | ||
|
||
void main() { | ||
/* SNIPPET START */ | ||
|
||
testWidgets('override repositoryProvider', (tester) async { | ||
await tester.pumpWidget( | ||
ProviderScope( | ||
overrides: [ | ||
// Surcharge le comportement de repositoryProvider pour qu'il renvoie | ||
// FakeRepository au lieu de Repository. | ||
/* highlight-start */ | ||
repositoryProvider.overrideWithValue(FakeRepository()) | ||
/* highlight-end */ | ||
// Il n'est pas nécessaire de surcharger `todoListProvider`, | ||
// il utilisera automatiquement le repositoryProvider surchargé. | ||
], | ||
child: const MyApp(), | ||
), | ||
); | ||
}); | ||
|
||
/* SNIPPET END */ | ||
} |
98 changes: 98 additions & 0 deletions
98
website/i18n/fr/docusaurus-plugin-content-docs/current/cookbooks/testing_full.dart
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
import 'package:flutter/material.dart'; | ||
import 'package:flutter_riverpod/flutter_riverpod.dart'; | ||
import 'package:flutter_test/flutter_test.dart'; | ||
|
||
class Repository { | ||
Future<List<Todo>> fetchTodos() async => []; | ||
} | ||
|
||
class Todo { | ||
Todo({ | ||
required this.id, | ||
required this.label, | ||
required this.completed, | ||
}); | ||
|
||
final String id; | ||
final String label; | ||
final bool completed; | ||
} | ||
|
||
// Nous exposons notre instance de référentiel dans un provider | ||
final repositoryProvider = Provider((ref) => Repository()); | ||
|
||
/// La liste des todos. Ici, nous les récupérons simplement sur | ||
/// le serveur en utilisant [Repository] et ne faisons rien d'autre. | ||
final todoListProvider = FutureProvider((ref) async { | ||
// Obtention de l'instance Repository | ||
final repository = ref.read(repositoryProvider); | ||
|
||
// Récupérer les todos et les exposer à l'interface utilisateur. | ||
return repository.fetchTodos(); | ||
}); | ||
|
||
/// Une implémentation simulée de Repository qui renvoie une liste prédéfinie de todos. | ||
class FakeRepository implements Repository { | ||
@override | ||
Future<List<Todo>> fetchTodos() async { | ||
return [ | ||
Todo(id: '42', label: 'Hello world', completed: false), | ||
]; | ||
} | ||
} | ||
|
||
class TodoItem extends StatelessWidget { | ||
const TodoItem({super.key, required this.todo}); | ||
final Todo todo; | ||
@override | ||
Widget build(BuildContext context) { | ||
return Text(todo.label); | ||
} | ||
} | ||
|
||
void main() { | ||
testWidgets('override repositoryProvider', (tester) async { | ||
await tester.pumpWidget( | ||
ProviderScope( | ||
overrides: [ | ||
repositoryProvider.overrideWithValue(FakeRepository()), | ||
], | ||
// Notre application, qui lira le todoListProvider pour afficher la liste des todos à faire. | ||
// Vous pouvez l'extraire dans un widget MyApp | ||
child: MaterialApp( | ||
home: Scaffold( | ||
body: Consumer(builder: (context, ref, _) { | ||
final todos = ref.watch(todoListProvider); | ||
// La liste des todos est en cours de chargement ou en erreur | ||
if (todos.asData == null) { | ||
return const CircularProgressIndicator(); | ||
} | ||
return ListView( | ||
children: [ | ||
for (final todo in todos.asData!.value) TodoItem(todo: todo) | ||
], | ||
); | ||
}), | ||
), | ||
), | ||
), | ||
); | ||
|
||
// Le premier frame est un état de chargement. | ||
expect(find.byType(CircularProgressIndicator), findsOneWidget); | ||
|
||
// Re-render. TodoListProvider devrait avoir fini de récupérer les todos maintenant | ||
await tester.pump(); | ||
|
||
// Plus de chargement | ||
expect(find.byType(CircularProgressIndicator), findsNothing); | ||
|
||
// Rendu d'un TodoItem avec les données renvoyées par FakeRepository | ||
expect(tester.widgetList(find.byType(TodoItem)), [ | ||
isA<TodoItem>() | ||
.having((s) => s.todo.id, 'todo.id', '42') | ||
.having((s) => s.todo.label, 'todo.label', 'Hello world') | ||
.having((s) => s.todo.completed, 'todo.completed', false), | ||
]); | ||
}); | ||
} |
Oops, something went wrong.